Home > Enterprise >  Avoid infinite loop on React - useState
Avoid infinite loop on React - useState

Time:10-28

How do I put a function (that is on a context) that is exported and also receives a parameter inside a useEffect so the setState inside that function doesn't cause infinite re-renders.

function:

export const PokemonProvider = ({children} : {children: ReactNode}) => {
    const [pokemon, setPokemon] = useLocalStorage<Pokemon[]>('pokemon', [{id: 123, name: 'mariomon', type: 'fogo', imageUrl: 'www.google.com'}]);

    const getPokemon = (newlyPokemon : Pokemon | null) => {
        newlyPokemon && setPokemon(prevState => [...prevState, newlyPokemon]);
    };

    return <PokemonContext.Provider value={{getPokemon, pokemon}}>
        {children}
    </PokemonContext.Provider>
}

getPokemon might be the issue here and even though my knowledge on React is limited how do I access newlyPokemon if I use a useCallback e.g? should I use a useRef and assign it the newlyPokemon value on getPokemon and then setPokemon inside a useEffect?

help needed, thanks!

CodePudding user response:

useCallback doesn't care how many parameters your callback has, since that doesn't change the location of where the function is stored.

There is no useEffect in the code provided.

If the useLocalStorage hook is written in the correct way, it's setter function should already be wrapped in a useCallback so it's memory location shouldn't ever change.

When you wrap your getPokemon in useCallback, its only dependency is setPokemon.

const getPokemon = useCallback((newlyPokemon : Pokemon | null) => {
  newlyPokemon && setPokemon(prevState => [...prevState, newlyPokemon]);
}, [setPokemon]);

If you're worried about rerenders, look into a state manager to control which elements get rerendered since any change to pokemon will cause every child of the PokemonProvider to rerender

  • Related