React собственный список API фильтрации

Я создаю свое первое реагирующее нативное приложение и подключаю свое приложение к издевательскому 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>   
    )
  }
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
3 323
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, что данные, возвращенные из вашего 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. Наконец, имейте в виду, что фильтрация также чувствительна к регистру.

Обновление 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
    });
}

Спасибо за ваш ответ. При использовании вашего метода FlatList пуст, пока я не найду строку. Я пытаюсь изолировать dataSource и добавить эти данные в filteredRows вот так filteredRows:dataSource в функции API this.state, но он возвращается с dataSource not found

Salman 20.02.2019 00:08

Не за что :-) Если я правильно понимаю, вы хотите, чтобы все данные restaurant отображались и отображались по умолчанию, а затем чтобы фильтрация вступала в силу только тогда, когда в поле поиска указана строка поиска?

Dacre Denny 20.02.2019 00:32

Это правильно. Так он работал с файлом data.js

Salman 20.02.2019 01:14

Ага `Вид Источник: ответ Json.restaurants, ` помогло! Спасибо! Не знал, как добавить вторую переменную.

Salman 20.02.2019 19:34

Другие вопросы по теме