skip to Main Content

I am learning React Native and I have a problem with the search bar, here I put my code.

export default SearchBar = ({ setPokemonDetails, pokemonsList }) => {

    const handlePokemonSearch = (text) => {
        const filteredItems = pokemonsList.filter(item => {
            return item.name.toLowerCase().includes(text.toLowerCase())
        })
        setPokemonDetails(filteredItems)
    }

    return (
        <View style={styles.container}>
            <TextInput style={styles.textInput} placeholder="Search Pokemon"
                onChangeText={(text) => {
                    handlePokemonSearch(text)
                }} />
        </View>
    );
}

Here is The Home Component, where I call de SearchBar Component:ç

export default function Home() {

const { pokemonDetails, setPokemonDetails, setIsLoading, isLoading, isError } = useFetchPokemons()

return (
    <View style={{ padding: 10 }}>
        <SearchBar setPokemonDetails={setPokemonDetails} pokemonsList={pokemonDetails} />
        <FlatList
            data={pokemonDetails}
            keyExtractor={(item) => item.name}
            renderItem={({ item }) => <Card pokemon={item} />}
        />
    </View>
);

}

This code works halfway because it filters really well while you are writting BUT, when you delete some letters, it does not filter again. For example:

I have an array with this pokemons:

  • Charmander
  • Charmeleon
  • Charizard

If I write ‘charm’, the search bar finds correctly there are only 2 (Charmander and Charmeleon), BUT if delete the ‘m’ letter, it does not show the 3 pokemons again and keep showing Charmander and Charmeleon.

Does anyone knows how can I solve this problem?

2

Answers


  1. I think to be able to better diagnose the issue, we would need to look at how you are calling your SearchBar component on your main screen. Could it be that setPokemonDetails sets the state of pokemonsList, causing this issue? For example, you might not be using two separate state variables to store the PokemonList as well as PokemonDetails.

    export default function MainScreen() {
      const [pokemonDetails, setPokemonDetails] = useState([]);
      const [pokemonsList, setPokemonsList] = useState([
        { name: 'Charmander' },
        { name: 'Charmeleon' },
        { name: 'Charizard' },
      ]);
    
      return (
        <View>
          <SearchBar setPokemonDetails={setPokemonDetails} pokemonsList={pokemonsList} />
    
          <FlatList
            data={pokemonDetails}
            keyExtractor={(item) => item.name}
            renderItem={({ item }) => (
              <View>
                <Text>{item.name}</Text>
              </View>
            )}
          />
        </View>
      );
    }
    

    I would make use of console.log() within handlePokemonSearch and see how pokemonsList as well as the filteredItems vary with text input.

    Hope this helps in any small way!

    Login or Signup to reply.
  2. When you setPokemonDetails(filteredItems), you are permanently trimming down the list that <SearchBar /> receives in its pokemonsList prop. You don’t want to alter the list when you are searching items, you simply want a filtered view of it to be rendered. So instead of setting the list itself, you need to track a new piece of state for the search text and set that instead.

    As an example:

    export default SearchBar = ({ setSearchText, pokemonsList }) => {
        const handlePokemonSearch = (text) => {
            setSearchText(filteredItems);
        };
    
        return (
            <View style={styles.container}>
                <TextInput
                    style={styles.textInput}
                    placeholder="Search Pokemon"
                    onChangeText={(text) => {
                        handlePokemonSearch(text);
                    }}
                />
            />
        );
    };
    
    export default PokemonsList = ({ initialPokemonsList }) => {
        // For explicitness, setPokemonDetails is defined but unused
        const [pokemonsList, setPokemonDetails] = useState([])
        const [searchText, setSearchText] = useState("");
    
        const filteredItems = pokemonsList.filter((item) => {
            return item.name.toLowerCase().includes(searchText.toLowerCase());
        });
    
        return (
            <>
                <SearchBar setSearchText={setSearchText} />
                <PokemonsList pokemonsList={filteredItems} />
            </>
        )
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search