【问题标题】:React native Filtering API flatlistReact 本机过滤 API 平面列表
【发布时间】:2019-02-19 21:07:11
【问题描述】:

我正在构建我的第一个 react 原生应用并将我的应用连接到一个可模拟的 API

之前我有一个 data.js 文件,但最近想使用实时 API 测试应用程序。

现在我在通过 API 过滤时遇到问题。在此之前,我会导入我的 Data.JS 文件并提取对象并将其置于我的状态。然后我将它设置为等于过滤的对象。

现在我已经用我的 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>   
    )
  }

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    看起来data returned from your 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(),您可能会发现此过滤行为的更简洁替代方案。希望对您有所帮助!

    更新

    此外,要使过滤生效,请记住将&lt;FlatList/&gt; 上的data 属性更新为您的状态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 中,就像 API this.state 函数中的 filteredRows:dataSource 一样,但它返回 dataSource not found
    • 不客气 :-) 如果我理解正确,您希望所有 restaurant 数据默认列出并可见,然后只有在提供搜索字符串时过滤才会生效在搜索字段中?
    • 没错。这就是它过去使用 data.js 文件的方式
    • 是的`viewSource:responseJson.restraunts,`帮助!谢谢!不确定如何添加第二个变量。
    猜你喜欢
    • 2020-09-05
    • 2022-01-08
    • 2022-01-22
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 2021-01-08
    相关资源
    最近更新 更多