简体   繁体   中英

How to search data efficiently with React Native ListView

I am trying to implement a filter and search function that would allow user to type in keyword and return result(array) and re-render the row

This is the event arrays that being passed in into the createDataSource function

在此处输入图片说明

The problem I am having now is my search function can't perform filter and will return the entire parent object although I specifically return the indexed object.

Here's what I got so far

class Search extends Component {

  state = { isRefreshing: false, searchText: '' }

  componentWillMount() {
    this.createDataSource(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.createDataSource(nextProps);
    if (nextProps) {
      this.setState({ isRefreshing: false })
    }
  }

  createDataSource({ events }) {
    const ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });
    this.dataSource = ds.cloneWithRows(events);
  }

  //return arrays of event from events
  renderRow(event) {
    return <EventItem event={event} />;
  }

  onRefresh = () => {
    this.setState({ isRefreshing: true });
    this.props.pullEventData()
  }

  setSearchText(event) {
   let searchText = event.nativeEvent.text;
   this.setState({ searchText })

   var eventLength = this.props.events.length
   var events = this.props.events

   const filteredEvents = this.props.events.filter(search)
   console.log(filteredEvents);

   function search() {
     for (var i = 0; i < eventLength; i++) {
       if (events[i].title === searchText) {
         console.log(events[i].title)
         return events[i];
       }
     }
   }
  }

  render() {
    const { skeleton, centerEverything, container, listViewContainer, makeItTop,
    textContainer, titleContainer, descContainer, title, desc, listContainer } = styles;

    return(
      <View style={[container, centerEverything]}>
        <TextInput
           style={styles.searchBar}
           value={this.state.searchText}
           onChange={this.setSearchText.bind(this)}
           placeholder="Search" />
        <ListView
          contentContainerStyle={styles.listViewContainer}
          enableEmptySections
          dataSource={this.dataSource}
          renderRow={this.renderRow}
          refreshControl={
            <RefreshControl
              refreshing={this.state.isRefreshing}
              onRefresh={this.onRefresh}
              title="Loading data..."
              progressBackgroundColor="#ffff00"
            />
          }
        />
      </View>
    )
  }
}

在此处输入图片说明

As you can see from the image above, my code requires me to type in the full query text to display the result. And it displays all the seven array objects? why's that?

The syntax of Array.prototype.filter is wrong... it should take a callback that will be the item being evaluated for filtering.. if you return true it will keep it.

function search(event) {
  return ~event.title.indexOf(searchText)
}

You could even make the inline like..

const filteredEvents = this.props.events.filter(event => ~event.title.indexOf(searchText))

For understanding my use of ~ , read The Great Mystery of the Tilde .

Since filter returns a new array, you should be able to clone your dataSource with it. If you didn't use filter , you would have to call events.slice() to return a new array. Otherwise, the ListView doesn't pickup the changes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM