我正在尝试根据搜索栏文本搜索平面列表。我遇到的问题是,当用户输入错误时...说他们想输入“汉堡”但是错误地键入“burget”然后它不会返回任何内容。当用户删除“t”时,它应该再次重新呈现平面列表,最后一个文本与“burge”部分匹配。
注意:使用react-native-elements搜索栏,它允许我只用e或事件来调用文本。
到目前为止我在Main.js文件中的内容:
searchText = (e) => {
let text = e.toLowerCase();
let trucks = this.state.data;
// search by food truck name
let filteredName = trucks.filter((truck) => {
return truck.name.toLowerCase().match(text);
});
// if no match and text is empty
if(!text || text === '') {
console.log('change state');
this.setState({
data: initial
});
}
// if no name matches to text output
else if(!Array.isArray(filteredName) && !filteredName.length) {
console.log("not name");
this.setState({
data: [],
});
}
// if name matches then display
else if(Array.isArray(filteredName)) {
console.log('Name');
this.setState({
data: filteredName,
});
}
};
<View style={styles.container}>
<SearchBar
round
lightTheme
containerStyle={styles.search}
ref="search"
textInputRef="searchText"
onChangeText={this.searchText.bind(this)}
placeholder='Search by Truck Name...'
/>
<TruckList getTruck={(truck) => this.setTruck(truck)} truckScreen={this.truckScreen} data={this.state.data}/>
</View>
然后是TruckList.JS:
export default class TruckList extends Component {
// rendering truck screen
renderTruckScreen = (item) => {
this.props.truckScreen();
this.props.getTruck(item);
}
render() {
return(
<List style={styles.list}>
<FlatList
data={this.props.data}
renderItem={({ item }) => (
<ListItem
roundAvatar
avatar={{uri: item.pic1}}
avatarStyle={styles.avatar}
title={item.name}
titleStyle={styles.title}
subtitle={
<View style={styles.subtitleView}>
<Text style={styles.subtitleFood}>{item.food}</Text>
<View style={styles.subtitleInfo}>
<Icon
name="favorite"
size={20}
color={"#f44336"}
style={styles.subtitleFavorite}
/>
<Text style={styles.subtitleFavoriteText}>{item.favorited} favorited</Text>
</View>
</View>
}
onPress={() => this.renderTruckScreen(item)}
/>
)}
keyExtractor={(item) => item.uid}
ListFooterComponent={this.footer}
/>
</List>
)
}
}
我尝试过其他一些方法无济于事。我见过的唯一可用于React Native的解决方案是ListView,它会及时折旧。所以我试图用新的FlatList组件来做这件事。
感谢您的帮助!
答案 0 :(得分:14)
当我尝试在新的FlatList组件上实现过滤器/搜索功能时,我今天遇到了同样的问题。这就是我设法解决它的方法:
通过在名为noData的父组件状态中创建另一个项目,可以在没有与搜索匹配的结果时将其设置为true,然后有条件地呈现FlatList。
我的实现与您的实现略有不同,但如果我必须调整您的代码,它将看起来像这样:
Searchtext功能:
searchText = (e) => {
let text = e.toLowerCase()
let trucks = this.state.data
let filteredName = trucks.filter((item) => {
return item.name.toLowerCase().match(text)
})
if (!text || text === '') {
this.setState({
data: initial
})
} else if (!Array.isArray(filteredName) && !filteredName.length) {
// set no data flag to true so as to render flatlist conditionally
this.setState({
noData: true
})
} else if (Array.isArray(filteredName)) {
this.setState({
noData: false,
data: filteredName
})
}
}
然后将noData bool传递给您的TruckList组件:
<TruckList getTruck={(truck) => this.setTruck(truck)}
truckScreen={this.truckScreen} data={this.state.data} noData={this.state.noData}/>
只有在有结果的情况下才会在TruckList组件中渲染FlatList:
<List style={styles.list}>
{this.props.noData ? <Text>NoData</Text> : <FlatList {...} />}
</List>
然后应该处理用户输入错误 - 因为它会在没有结果时立即重新呈现平面列表,并在您删除输入错误时记住以前的搜索状态..
如果有帮助,请告诉我!
答案 1 :(得分:6)
<强>更新强> This blog可以帮助您更好地理解FlatList中的搜索。
<强>供参考:强> 如果您有大量在线数据,那么您也可以使用algolia。
我为我调整了上面的代码,以使其正常工作。原因是当用户删除最后一个错误的字符时,代码从先前的搜索列表(状态)中搜索这个新字符串,该字符串不包含所有对象,尽管它必须从可用的完整列表中搜索。所以,我现在有两个清单。一个包含完整的对象列表,第二个包含仅在搜索时更改的对象的渲染列表。
handleSearchInput(e){
let text = e.toLowerCase()
let fullList = this.state.fullListData;
let filteredList = fullList.filter((item) => { // search from a full list, and not from a previous search results list
if(item.guest.fullname.toLowerCase().match(text))
return item;
})
if (!text || text === '') {
this.setState({
renderedListData: fullList,
noData:false,
})
} else if (!filteredList.length) {
// set no data flag to true so as to render flatlist conditionally
this.setState({
noData: true
})
}
else if (Array.isArray(filteredList)) {
this.setState({
noData: false,
renderedListData: filteredList
})
}
}
答案 2 :(得分:2)
这是我的解决方法:
您需要备份数据
this.state = {
data: [],
backup: []
}
关于搜索方法
search = txt => {
let text = txt.toLowerCase()
let tracks = this.state.backup
let filterTracks = tracks.filter(item => {
if(item.name.toLowerCase().match(text)) {
return item
}
})
this.setState({ data: filterTracks })
}
说明:在数据上调用setState时,它将更改为当前状态,并且无法再次更改。
因此备份数据将处理以过滤您的数据。
答案 3 :(得分:2)
constructor(props) {
super(props);
this.state = {
data: [],
value: ""
};
this.arrayholder = [];
}
下一步获取数据:-
_fetchdata = async () => {
const response = await fetch("https://randomuser.me/api?results=10");
const json = await response.json();
this.setState({ data: json.results });
this.arrayholder = json.results;
};
接下来定义searchFilterFunction:-
searchFilterFunction = text => {
this.setState({
value: text
});
const newData = this.arrayholder.filter(item => {
const itemData = item.email.toLowerCase();
const textData = text.toLowerCase();
return itemData.indexOf(textData) > -1;
});
this.setState({ data: newData });
};
呈现searchView:-
<TextInput
style={{ height: 40, borderColor: "gray", borderWidth: 1 }}
onChangeText={text => this.searchFilterFunction(text)}
/>
不要忘记从“ react-native”中导入TextInput;
答案 4 :(得分:1)
对于有用的内存中搜索,您应该分别保存初始数据。
对此,我有更简单的解决方案。
这种针对FlatList数据进行内存中搜索的解决方案,并使用它String.prototype .includes()方法搜索子字符串。
您可以在本要点中找到该组件的完整源代码; https://gist.github.com/metehansenol/46d065b132dd8916159910d5e9586058
我的初始状态; </ p>
this.state = {
searchText: "",
data: [],
filteredData: []
};
我的SearchBar组件(它来自react-native-elements包);
<SearchBar
round={true}
lightTheme={true}
placeholder="Search..."
autoCapitalize='none'
autoCorrect={false}
onChangeText={this.search}
value={this.state.searchText}
/>
我的搜索方法;
search = (searchText) => {
this.setState({searchText: searchText});
let filteredData = this.state.data.filter(function (item) {
return item.description.includes(searchText);
});
this.setState({filteredData: filteredData});
};
最后是我的FlatList的数据源表达式;
<FlatList
data={this.state.filteredData && this.state.filteredData.length > 0 ? this.state.filteredData : this.state.data}
keyExtractor={(item) => `item-${item.id}`}
renderItem={({item}) => <ListItem
id={item.id}
code={item.code}
description={item.description}
/>}
/>
快乐的编码...
答案 5 :(得分:0)
FYI :data
是要搜索的subtext
,这是一种基本搜索,因为要搜索的数据被查看到数组的每个列表项中,是array/array
的实际objects
的副本,最后设置其状态,无论是否找到0
与(actualArray.length-1
)和临时arrayData
之间的匹配项如果至少存在一个匹配项,则呈现actualArray
implementSearch(data) {
temp = [];
var count = 0;
var searchData = data.toUpperCase();
var arr = this.state.personDetail;
for (var i = 0; i < arr.length; i++) {
var actualData = arr[i].name.toUpperCase();
if (actualData.includes(searchData)) {
temp.push(arr[i]);
count++;
}
}
this.setState({
tempArray: temp,
matches: count,
searchValue: data
});
}
希望有帮助
答案 6 :(得分:0)
我的搜索方法;来自@ metehan-senol
search = (searchText) => {
this.setState({searchText: searchText});
let filteredData = this.state.data.filter(function (item) {
return item.description.includes(searchText);
});
this.setState({filteredData: filteredData});
};
像这样的搜索方法可以简化并得到Eslint证明
search = (searchText) => {
const searched = searchText.toLowerCase();
this.setState(prevState => ({
searchText: searched,
filteredData: prevState.data.filter(item =>
item.description.toLowerCase().includes(searched)
),
}));
};
答案 7 :(得分:0)
class MyComponent extends React.Component
constructor() {
// wrong retrun value from `foo()`, this.myProperty will be `Infinity`
this.myProperty = foo();
}
// Component methods here....
myFancyFunction() {
// This code will encounter `Malformed calls from JS: field sizes are different`
// `[xxxx, "<<Infinity>>", xxxxxxxxx, true]`
this.timer = setInterval(() => {
//Do something
}, this.myProperty); //<-- should never be `Infinity` here
}
}
答案 8 :(得分:0)
通过应用进行过滤
let filterData= data.filter((item) => {
return item.name.toLowerCase().match(text)
})
if (!text || text === '') {
this.setState({
datasource: initial
})
} else if (!Array.isArray(filterData) && !filterData.length) {
// set no data flag to true so as to render flatlist conditionally
this.setState({
noData: true
})
} else if (Array.isArray(filterData)) {
this.setState({
noData: false,`enter code here`
dataSource: filterData
})`enter code here`
}
答案 9 :(得分:0)
就性能而言,这不是最佳的解决方案,但是如果您没有大量数据,请随时使用此功能:
searchFilter () {
return this.props.data.filter((item) => {
const regex = new RegExp(this.state.searchInput, "gi")
return item.label.match(regex);
})
}
然后在您的FlatList组件中:
<FlatList
data={this.searchFilter()}
renderItem={this.renderItem}
keyExtractor={(item) => item.value}
/>
答案 10 :(得分:0)
您可以按照以下步骤搜索您的数据:
<TextInput onChangeText={(text) => searchData(text)} value={input} />
***Please Note *searchData is my function whom I passing a text prop***
const searchData = (text) => {
const newData = restaurantsData.filter((item) => {
return item.title.search(text) > -1;
});
setRestaurantsData(newData);
setInput(text);
};
注意 RestaurantsData 是我的数据数组