我正在构建我的第一个React本机应用程序并将我的应用程序连接到可模拟的API
之前我有一个data.js文件,但最近想使用实时API测试该应用程序。
现在我在过滤API时遇到问题。在开始之前,我将导入我的Data.JS文件并提取对象并将其置于我的状态。然后,我将其设置为filteredObject。
现在我已经用API替换了数据文件
我有一个运行here的测试
我期望的是:
通过我的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>
)
}
渲染平面列表
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>
)
}
答案 0 :(得分:1)
data returned from your API似乎不一致;对于某些行,restaurant
不存在。
考虑像这样修改setSearchText()
方法,以解决不包含row
字符串字段的restraunt
项:
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
上的<FlatList/>
属性更新为您的状态filteredRows
字段,而不是dataSource
。最后,请记住,过滤也区分大小写。
要获得所需的过滤性能,可以对组件进行以下调整:
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
});
}