简体   繁体   English

在 React Native Flatlist 中添加搜索栏没有响应

[英]Adding Search Bar In React Native Flatlist Is not Responding

In my React Native application I want to be able to search and display songs, I have tried implementing search function, but none seems to work.在我的 React Native 应用程序中,我希望能够搜索和显示歌曲,我尝试实现搜索 function,但似乎没有一个工作。 The code below only allows me to type one letter, and when I type one letter my android device keyboard disappears my list will still remain (no search will be triggered).下面的代码只允许我输入一个字母,当我输入一个字母时,我的 android 设备键盘消失了,我的列表仍然存在(不会触发搜索)。

Please I need help to make the search feature work in order for my search songs to display when User searches for songs.请我需要帮助以使搜索功能正常工作,以便在用户搜索歌曲时显示我的搜索歌曲。

Here's my player list code:这是我的播放器列表代码:

 import React, { useEffect, useState } from 'react'; import { SafeAreaView, View, FlatList, ScrollView, TouchableOpacity, ActivityIndicator, TextInput, } from 'react-native'; import Sound from 'react-native-sound'; import { Avatar, Text } from '@ui-kitten/components'; import Ionicons from 'react-native-vector-icons/Ionicons'; import filter from 'lodash.filter'; import songs from '../../SongData'; import styles from './styles'; const SonglistScreen = () => { const [isDisabled, setisDisabled] = useState(false); const [loading, setLoading] = useState(false); const [isPlayed, setIsPlayed] = useState(false); const [data, setData] = useState([]); const [query, setQuery] = useState(''); const [song, setSong] = useState([]); const [fullData, setFullData] = useState([]); useEffect(() => { getData(); }, []); const getData = () => { const res = (songs); setData(res); setFullData(res); }; .....//......// const renderItem = ({ item, index }) => ( <ScrollView style={{flex: 1}}> <View style={styles.item}> <Avatar source={{ uri: item.picture }} style={{ marginRight: 16 }} size='giant' /> <Text style={styles.title} category='s1'> {item.title} </Text> </View> <Text style={{ color: '#444', fontSize: 11, marginLeft: 112, marginVertical: -20, bottom: 27 }} category='s1' >{item.ArtistName} </Text> <Text style={{ color: '#999', marginLeft: 110, marginVertical: -20, top: 10 }} category='s1' >Genre: {item.genre} </Text> <View style={{flexDirection: 'row', left: '230%', bottom: '7%'}}> <TouchableOpacity onPress={()=>playSound(item, index)} style={{padding: 10, top: 30, left: 30}} > <Ionicons name="play" color={isPlayed? 'red': '#555555'} size={22} /> </TouchableOpacity> <TouchableOpacity onPress={()=>stopSound(index)} style={{padding: 10, top: 30, left: 20}} > <Ionicons name="stop" color="#555555" size={22} /> </TouchableOpacity> </View> </ScrollView> ); const handleSearch = text => { let newData = songs.filter(item =>{ const itemData = `${item.title.toUpperCase()}`; const textData = text.toUpperCase(); if (text.length > 0) { return itemData.indexOf(textData) > -1; } }); setData(newData); setQuery(text); }; const renderHeader = () => { return ( <View style={{ backgroundColor: '#fff', padding: 10, marginVertical: 10, borderRadius: 20 }} > <TextInput autoCapitalize="none" autoCorrect={false} clearButtonMode="always" value={query} onChangeText={text => handleSearch(text)} placeholder="Search songs" style={{ backgroundColor: '#fff', paddingHorizontal: 20 }} /> </View> ) }; const renderFooter = () => { if (:loading) return null return ( <View style={{ paddingVertical, 15: borderTopWidth, 1: borderColor, '#CED0CE'; }} > <ActivityIndicator animating size='large' /> </View> ). }...../...../ return ( <SafeAreaView style={styles.container}> <FlatList data={songs} renderItem={renderItem} keyExtractor={item => item;id} ItemSeparatorComponent={renderSeparator} ListHeaderComponent={renderHeader} ListFooterComponent={renderFooter} /> </SafeAreaView> ); }

This is the data I want to search and display songdata.js:这是我要搜索和显示 songdata.js 的数据:

 const songs = [ { id: 1, title: 'Hero', ArtistName: 'Bethany Dilon', genre: 'pop', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.18169-9/16195530_10211997136709517_8578854309931959016_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=09cbfe&_nc_eui2=AeEvt5zlNj1bM87SMIgRXz8VjFbfh8f8mfyMVt-Hx_yZ_ISR6pzt6j1tOqssNCwDfnM&_nc_ohc=oQeQeYLPRz8AX_n81Yh&_nc_ht=scontent-los2-1.xx&oh=d87b3097c543a39067095bacfbeb004d&oe=609BF1DC', url: require('../../assets/songs/Hero.mp3'), }, { id: 2, title: 'Advertising URL', ArtistName: 'Bethany Dilon', genre: 'Soft Rock', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://raw.githubusercontent.com/zmxv/react-native-sound-demo/master/advertising.mp3', }, { id: 3, title: 'Stronger', ArtistName: 'Bethany Dilon', genre: 'Country', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: require('../../assets/songs/Stronger.mp3'), }, { id: 4, title: 'Faded', ArtistName: 'Luchee', genre: 'Techno', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/Faded.mp3', }, { id: 5, title: 'Solo', ArtistName: 'Solo Cosmos', genre: 'Afrobeat', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/Solo.mp3', }, { id: 6, title: 'Death Bed', ArtistName: 'Omowunmi feat Wizkid', genre: 'Afrocentric', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/death%20bed.mp3', }, { id: 7, title: 'Hero', ArtistName: 'Bethany Dilon', genre: 'pop', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.18169-9/16195530_10211997136709517_8578854309931959016_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=09cbfe&_nc_eui2=AeEvt5zlNj1bM87SMIgRXz8VjFbfh8f8mfyMVt-Hx_yZ_ISR6pzt6j1tOqssNCwDfnM&_nc_ohc=oQeQeYLPRz8AX_n81Yh&_nc_ht=scontent-los2-1.xx&oh=d87b3097c543a39067095bacfbeb004d&oe=609BF1DC', url: require('../../assets/songs/Hero.mp3'), }, { id: 8, title: 'Advertising URL', ArtistName: 'Bethany Dilon', genre: 'Soft Rock', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://raw.githubusercontent.com/zmxv/react-native-sound-demo/master/advertising.mp3', }, { id: 9, title: 'Stronger', ArtistName: 'Bethany Dilon', genre: 'Country', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: require('../../assets/songs/Stronger.mp3'), }, { id: 10, title: 'Faded', ArtistName: 'Luchee', genre: 'Techno', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/Faded.mp3', }, { id: 11, title: 'Solo', ArtistName: 'Solo Cosmos', genre: 'Afrobeat', isRequire: true, picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/Solo.mp3', }, { id: 12, title: 'Death Bed', ArtistName: 'Omowunmi feat Wizkid', genre: 'Afrocentric', picture: 'https://scontent-los2-1.xx.fbcdn.net/v/t1.6435-0/s640x640/169534769_1185223728571457_6192837830233317030_n.jpg?_nc_cat=101&ccb=1-3&_nc_sid=9267fe&_nc_eui2=AeH2splO8pf4k-atqrUeWWApKjkWnAsELXsqORacCwQte9doNY5rNtBrWht-o_CYYR4&_nc_ohc=plbZA_Pv91EAX_quQhG&_nc_ht=scontent-los2-1.xx&tp=7&oh=abec7b3bd8ddc13b6c3c0c510a33d8dc&oe=60997696', url: 'https://github.com/ShivamJoker/sample-songs/raw/master/death%20bed.mp3', }, ]; export default songs;

So, the thing here is that everything is inside the same component and when you run a setData or setQuery you update the whole component, and your keyboard is reseted.所以,这里的事情是所有东西都在同一个组件中,当你运行setDatasetQuery时,你会更新整个组件,并且你的键盘会被重置。

About your list not been updated, it seems to be a small typo on your code:关于您的列表未更新,您的代码似乎是一个小错字:

return (
  <SafeAreaView style={styles.container}>
    <FlatList
      // data={songs} <-- here you should be using data
      data={data} // something like this
      renderItem={renderItem}
      keyExtractor={item => item.id}
      ItemSeparatorComponent={renderSeparator}
      ListHeaderComponent={renderHeader}
      ListFooterComponent={renderFooter}
    />
  </SafeAreaView>
);

But you would also need to update your state declarations as well so you don't start with an empty list, from this:但是您还需要更新您的 state 声明,这样您就不会从一个空列表开始,如下所示:

const [data, setData] = useState([]);

to this:对此:

const [data, setData] = useState(songs);

Ok, this should solve the no filter on the list as now you will be using the variable you set on your filter function, but the problem about your keyboard dismissing will keep happening as you update your whole component each text change.好的,这应该可以解决列表中的无过滤器问题,因为现在您将使用您在过滤器 function 上设置的变量,但是随着您每次文本更改更新整个组件,有关键盘关闭的问题将继续发生。 Here's a good solution in my opinion:我认为这是一个很好的解决方案:

Use some sort of global state management (Eg.: Context or Redux, you could also achieve this solution with mobx) this way you can create a separated component called <ListHeader /> for example and put your query update there and update the list value on the global state, this will not cause a full reload on your component, just the list will update and you can keep the field focus, maybe it's a new concept for you so I'm sharing an example using Context here:使用某种全局 state 管理(例如:上下文或 Redux,您也可以使用 mobx 实现此解决方案)这样您可以创建一个名为<ListHeader />的单独组件,例如并将您的查询更新放在那里并更新列表值在全局 state 上,这不会导致您的组件完全重新加载,只是列表会更新,您可以保持字段焦点,也许这对您来说是一个新概念,所以我在这里分享一个使用 Context 的示例:

Working Example:工作示例:

https://codesandbox.io/s/contextexample-p28z5?file=/src/App.js https://codesandbox.io/s/contextexample-p28z5?file=/src/App.js

Static Code: Static 代码:

    import React, { useContext, useState } from "react";
import { Text, View, FlatList, TextInput } from "react-native";

const data = [
  { name: "qweqwe" },
  { name: "aaaaaa" },
  { name: "eeeeeeeee" },
  { name: "4" }
];

// List Context and ListProvider can be togheter in the same file
const ListContext = React.createContext({
  list: [],
  setList: () => {}
});
const ListProvider = ({ children }) => {
  const [list, setList] = useState(data);

  return (
    <ListContext.Provider value={{ list, setList }}>
      {children}
    </ListContext.Provider>
  );
};

const Item = ({ item }) => {
  return (
    <View>
      <Text>{item.name}</Text>
    </View>
  );
};

const Header = () => {
  const [text, setText] = useState("");
  const listContext = useContext(ListContext);

  const updateQuery = (str) => {
    listContext.setList(data.filter((d) => d.name.indexOf(str) > -1));
    setText(str);
  };

  return (
    <View>
      <TextInput value={text} onChangeText={updateQuery} />
    </View>
  );
};

const ListScreen = () => {
  return (
    <ListContext.Consumer>
      {(context) => (
        <View style={{ flex: 1 }}>
          <FlatList
            data={context.list}
            keyExtractor={(i) => i.name}
            renderItem={({ item }) => <Item item={item} />}
            ListHeaderComponent={Header}
          />
        </View>
      )}
    </ListContext.Consumer>
  );
};

const App = () => {
  return (
    <ListProvider>
      <ListScreen />
    </ListProvider>
  );
};

export default App;

Wish success on your project.祝您的项目成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM