Я создаю свое первое реагирующее нативное приложение и подключаю свое приложение к издевательскому API.
Раньше у меня был файл data.js, но недавно я хотел протестировать приложение с живым API.
Теперь у меня проблемы с фильтрацией через мой API. Раньше я импортировал свой файл Data.JS, извлекал объект и помещал его в свое состояние. Затем я бы установил это равным filteredObject.
Теперь я заменил свой файл данных своим 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.info("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.info(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() таким образом, чтобы он учитывал элементы 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
});
}
Не за что :-) Если я правильно понимаю, вы хотите, чтобы все данные restaurant отображались и отображались по умолчанию, а затем чтобы фильтрация вступала в силу только тогда, когда в поле поиска указана строка поиска?
Это правильно. Так он работал с файлом data.js
Ага `Вид Источник: ответ Json.restaurants, ` помогло! Спасибо! Не знал, как добавить вторую переменную.
Спасибо за ваш ответ. При использовании вашего метода
FlatListпуст, пока я не найду строку. Я пытаюсь изолироватьdataSourceи добавить эти данные вfilteredRowsвот такfilteredRows:dataSourceв функции APIthis.state, но он возвращается сdataSource not found