反应本机Filtering API平面列表

时间:2019-02-19 21:07:11

标签: reactjs react-native

我正在构建我的第一个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>   
    )
  }

1 个答案:

答案 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。最后,请记住,过滤也区分大小写。

更新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
    });
}