Reputation: 457
I developed an application where I get an api (pokeAPI) with pokemons, and basically I have a global array with "myPokemons", so I want to display all my pokemons except the ones in that array, so I created the function "filterMyPokemons" that I filter the pokemons that should be displayed, and then I call this function in useEffect so that it is updated along with the page, putting a dependency array from the API list. The problem is that I now have an infinite loop that hurts the performance of the application.
import * as C from './styles';
import logo from '../../assets/pokelogo.png';
import { useContext, useState } from 'react';
import { useApi } from '../../hooks/useApi';
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import Pokelist from '../../components/PokeList';
import CatchingPokemonIcon from '@mui/icons-material/CatchingPokemon';
import CatchContext from '../../context/Context';
const Homepage = () => {
const api = useApi();
const { showMyPokemons } = useContext(CatchContext);
const navigate = useNavigate();
const [pokemonList, setPokemonList] = useState([]);
const [loading, setLoading] = useState(false);
const [text, setText] = useState('');
const [myPokemonsList, setMyPokemonsList] = useState([]);
const [pokemonListFiltered, setPokemonListFiltered] = useState([]);
useEffect (() => {
const getAllPokemons = async () => {
const myPokemons = await showMyPokemons();
const pokemon = await api.getAllPokemon();
setLoading(true);
setPokemonList(pokemon);
setMyPokemonsList(myPokemons);
setLoading(false);
}
filterMyPokemons();
getAllPokemons();
}, [myPokemonsList]);
const filterMyPokemons = async () => {
const filteredList = await pokemonList.filter(pokemons => !myPokemonsList.includes(pokemons.name))
return setPokemonListFiltered(filteredList);
};
const lowerSearch = text.toLocaleLowerCase();
const filteredPokemons = pokemonListFiltered.filter(pokemon => pokemon
.name.toLowerCase().includes(lowerSearch)
);
const handleHome = () => {
navigate('/')
}
const handleMyPokemons = () => {
navigate('/mypokemons')
}
return (
<C.Container>
<C.Logo>
<img src={logo} alt="" />
</C.Logo>
<C.Navbar>
<input
type="text"
placeholder='Busque um pokémon...'
onChange={(e) => setText(e.target.value)}
value={text}
/>
</C.Navbar>
<C.Pokedatabase onClick={handleMyPokemons}>
<button>Meus pokémons <i><CatchingPokemonIcon /></i></button>
</C.Pokedatabase>
<C.Pokelist>
{filteredPokemons.map(pokemon => {
return (
<Pokelist
name={pokemon.name}
/>
)
})}
</C.Pokelist>
</C.Container>
)
}
export default Homepage;
If I leave useEffect's dependency array empty, the items are not displayed, but if I leave any dependencies it causes an infinite loop. How to solve this problem?
Upvotes: 0
Views: 37
Reputation: 330
The problem comes with updating the myPokemonsList
array within the useEffect
hook that depends on that array.
useEffect (() => {
const getAllPokemons = async () => {
const myPokemons = await showMyPokemons();
const pokemon = await api.getAllPokemon();
setLoading(true);
setPokemonList(pokemon);
setMyPokemonsList(myPokemons); // Here's the infinite loop
setLoading(false);
}
filterMyPokemons();
getAllPokemons();
}, [myPokemonsList]); // Here's the infinite loop
You should have another use effect for updates on the myPokemonList
in order to avoid updating and depending on the same list.
Upvotes: 1