Mr. Robot
Mr. Robot

Reputation: 1824

How to search FlatList in React Native using search bar and Redux Hooks

I am trying to search a FlatList in React Native using react-native-dynamic-searchbar and Redux hooks. There's lots of info out there about how to do this but not using the dispatch hook.

My non-working code is as follows:

const Contacts = () => {
  const dispatch = useDispatch();
  const contacts = useSelector(state => state.user.parsedContacts);

  const renderContacts = contacts => {
    return (
      <ContactListItem
        name={contacts.item.full_name}
        phone={contacts.item.phone}
        isRegisteredUser={contacts.item.id !== 0 ? true : false}
      />
    )
  }

  const handleFilter = input => {
    dispatch(updateParsedContacts(contacts.filter(contact => contact.full_name.includes(input))));
  }

  if (contacts !== null) {
    return (
      <View>
        <StatusBar />
        <View style={styles.topMargin}>
        </View>
        <View style={styles.header}>
          <SearchBar
            iconColor="#EE578D"
            placeholder="Search Here..."
            onChangeText={handleFilter}
          />
        </View>
        <FlatList
          data={contacts}
          renderItem={renderContacts}
          initialNumToRender={5}
          maxToRenderPerBatch={10}
          windowSize={10}
          keyExtractor={(_, index) => index.toString()}
        />

I am trying to updated the FlatList in realtime when the user enters in put text in the search bar. The handleFilter function receives the input text but the Redux store is not updating properly. How should this be implemented to work?

Upvotes: 2

Views: 1356

Answers (1)

Incepter
Incepter

Reputation: 2958

There is a problem with your code:

Once you search, you update your main data list, and thus, when you research again, you search on the filtered list. If you delete your search characters you cannot go back to all results.

To avoid this, I recommend that either you add a new sub-state for filtered contract or that the filter is done at your component level:

const contacts = useSelector(state => state.user.parsedContacts);

// memoize a filtered contracts that is recalculated when either contracts of the input change
const filteredContracts = React.useMemo(() => {
  return contracts.filter(contact => contact.full_name.includes(input));
}, [contracts, input]);


// ... later
        <FlatList
          data={filteredContracts}
          renderItem={renderContacts}
          initialNumToRender={5}
          maxToRenderPerBatch={10}
          windowSize={10}
          keyExtractor={(_, index) => index.toString()}
        />

Upvotes: 3

Related Questions