我正在构建我的第一个React本地应用程序,并将我的应用程序连接到可模拟的API
之前我有一个data.js文件,但最近想用实时API测试该应用。
现在,我在过滤槽中的API时遇到问题。在随时随地,我会导入我的data.js文件并提取对象并将其放在我的状态中。然后,我将其设置为等于过滤的对象。
现在,我已经用我的API
替换了我的数据文件我在这里运行了一个测试
我期望的是:
要过滤我的flatlist
我得到了什么:
undefined is not an object (evaluating 'row.restraunt.indexOf')
获取API
export default class FetchExample extends React.Component {
static navigationOptions = {
header: null,
};
constructor(props){
super(props);
this.state ={
isLoading: true,
}
}
componentDidMount(){
return fetch('https://demo3381137.mockable.io/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.restraunts,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
过滤槽API
setSearchText(event) {
const searchText = event.nativeEvent.text;
// const textLength = this.state.rows.length;
const filteredTexts = this.state.dataSource.filter(row => {
return row.restraunt.indexOf(searchText) !== -1;
});
console.log("text: " + JSON.stringify(filteredTexts));
this.setState({
searchText,
filteredRows: filteredTexts
});
}
列表组件
renderRow = (rowData) => {
return (
<View>
<Text>
{rowData.item.restraunt}, {rowData.item.type}
</Text>
</View>
)
}
渲染flatlist
render() {
if(this.state.isLoading){
return(
<View style={styles.loading}>
<ActivityIndicator/>
</View>
)
}
return (
<View style={styles.container}>
{console.log(this.state.dataSource)}
<View style={styles.SearchBarContainer}>
<TextInput
placeholder="Search"
value={this.state.searchText}
onChange={this.setSearchText.bind(this)}
style={styles.searchBar}
underlineColorAndroid="black"
selectionColor="black"
/>
</View>
<FlatList
style={styles.listContainer}
data={this.state.dataSource}
renderItem={this.renderRow}
keyExtractor={(item, index) => index.toString()}
/>
</View>
)
}
看起来从API返回的数据不一致;对于某些行不存在restaurant
。
考虑这样修改您的setSearchText()
方法,以说明不包括restraunt
字符串字段的row
项目:
setSearchText(event) {
const searchText = event.nativeEvent.text;
const filteredTexts = this.state.dataSource.filter(row => {
/* If row.restraunt is present as a string, and includes searchText */
return (typeof row.restraunt === 'string') &&
row.restraunt.includes(searchText)
});
this.setState({
searchText,
filteredRows: filteredTexts
});
}
还请注意,此处的includes()
的使用,您可能会发现这种过滤行为的更简洁的替代方案。希望有帮助!
更新
此外,要进行过滤,请记住将data
Prop上的<FlatList/>
Prop更新为您的状态filteredRows
字段,而不是dataSource
。最后,请记住,过滤也对病例敏感。
更新2
要实现所需的过滤行为,您可以对组件进行以下调整:
componentDidMount(){
return fetch('https://demo3381137.mockable.io/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
/* Keep this, we'll base filtering on this data set */
dataSource: responseJson.restraunts,
/* Add this, to track what is presented to the user */
viewSource: responseJson.restraunts,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
render() {
if(this.state.isLoading){
return(
<View style={styles.loading}>
<ActivityIndicator/>
</View>
)
}
return (<View style={styles.container}>
<View style={styles.SearchBarContainer}>
<TextInput
placeholder="Search"
value={this.state.searchText}
onChange={this.setSearchText.bind(this)}
style={styles.searchBar}
underlineColorAndroid="black"
selectionColor="black"
/>
</View>
{/* Use state.viewSource as the data source for FlatList */}
<FlatList
style={styles.listContainer}
data={this.state.viewSource}
renderItem={this.renderRow}
keyExtractor={(item, index) => index.toString()} />
</View>)
}
setSearchText(event) {
const searchText = event.nativeEvent.text;
const filteredTexts = this.state.dataSource.filter(row => {
/* When no search text present, do not apply filtering */
if(!searchText) {
return true;
}
/* If row.restraunt is present as a string, and includes searchText */
return (typeof row.restraunt === 'string') &&
row.restraunt.includes(searchText)
});
this.setState({
searchText,
/* Update viewSource to ensure that filtered data is displayed */
viewSource: filteredTexts
});
}