在React Native平面列表中添加搜索栏没有响应



在我的React Native应用程序中,我希望能够搜索和显示歌曲,我尝试过实现搜索功能,但似乎都不起作用。下面的代码只允许我键入一个字母,当我键入一封字母时,我的android设备键盘消失了,我的列表仍将保留(不会触发搜索(。

请帮助我使搜索功能工作,以便在用户搜索歌曲时显示我的搜索歌曲。

这是我的玩家列表代码:

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>
);
}

这是我要搜索和显示的数据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;

所以,这里的问题是,所有东西都在同一个组件内,当你运行setDatasetQuery时,你会更新整个组件,并且你的键盘会重新设置种子。

关于你的列表没有更新,这似乎是你代码上的一个小错误:

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>
);

但你也需要更新你的状态声明,这样你就不会从一个空列表开始:

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

到此:

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

好吧,这应该可以解决列表中没有过滤器的问题,因为现在你将使用你在过滤器函数上设置的变量,但当你每次文本更改都更新整个组件时,键盘关闭的问题将不断发生。在我看来,这里有一个很好的解决方案:

使用某种全局状态管理(例如:Context或Redux,你也可以用mobx实现这个解决方案(。通过这种方式,你可以创建一个名为<ListHeader />的独立组件,并将查询更新放在那里,更新全局状态上的列表值,这不会导致组件上的完全重载,只是列表会更新,你可以保持字段焦点,也许这对你来说是一个新概念,所以我在这里分享一个使用上下文的例子:

工作示例:

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

静态代码:

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;

祝你的项目成功。

最新更新