Search code examples
javascriptreactjsreact-nativereact-native-sectionlist

Filter data in React Native Section List


I'm using React Native's SectionList. The data to the SectionList looks something like this

data: [
    {
      title: "Asia",
      data: ["Taj Mahal", "Great Wall of China", "Petra"]
    },
    {
      title: "South America",
      data: ["Machu Picchu", "Christ the Redeemer", "Chichen Itza"]
    },
    {
      title: "Europe",
      data: ["Roman Colosseum"]
    }
  ]

I have a Text Input using which I try to filter out contents in the SectionList. I tried using Array.filter() and it doesn't seem to work. It returns me the entire data without any filtering. So, I tried Array.some(). Now all the data items in the section are being filtered when even one item matches it. This behavior is expected out of Array.some(). But I'm confused why Array.filter() is not working in my case.

My SectionList looks something like this,

<SectionList 
      sections={this.state.data.filter(sectionData => {
        sectionData = sectionData.data;
        return sectionData.filter(data => {
          return data.includes(this.state.searchTerm);
        })
      })}
      renderSectionHeader={({ section: { title } }) => ( <Text style={{ fontWeight: "bold" }}>{title}</Text> )}
      renderItem={({ item }) => ( <Text style={styles.listItem}>{item}</Text>)}
      keyExtractor={item => item}
    />

Here's the link for Expo Playground if you wish to play with it online.


Solution

  • filter will create a new array with all the entries that returned a truthy value. Your second filter will always return at least an empty array, which is truthy, and thus you get all your sections in the final result.

    You could try a combination of reduce and filter instead:

    this.state.data.reduce((result, sectionData) => {
      const { title, data } = sectionData;
      const filteredData = data.filter(
        element => element.includes(this.state.searchTerm)
      );
    
      if (filteredData.length !== 0) {
        result.push({
          title,
          data: filteredData
        });
      }
    
      return result;
    }, [])