Im learning react and this is some demo code I have written. It does an initial request even though it’s inside of an useEffect with dependency. Why does it do that and how can i fix it?
import { useEffect, useState } from "react";
import BasicInfo from "./BasicInfo";
export default function MainInfo(){
const [searchByName, setSearchByName] = useState('');
const [pokemonInfo, setPokemonInfo] = useState({});
const [hasInfo, setHasInfo] = useState(false);
const [hasPressed, setHasPressed] = useState(false);
const handleSubmit = (e) =>{
e.preventDefault();
setHasPressed(true);
console.log(searchByName);
};
const changeHandler = (e) =>{
setSearchByName(e.target.value);
setHasPressed(false);
};
const buttonHandler = (e) =>{
setHasPressed(oldState => !oldState);
}
useEffect(() => {
fetch(`https://pokeapi.co/api/v2/pokemon/${searchByName}`)
.then(response => response.json())
.then(data => {
console.log(data)
setPokemonInfo(data)
setHasInfo(true)
})
.catch(error => console.error('Error fetching data', error))
},[hasPressed])
return(
<div>
<form onSubmit={handleSubmit}>
<input type="text" name="input" value={searchByName} onChange={changeHandler}></input>
<button onClick={buttonHandler}></button>
</form>
{hasInfo && pokemonInfo.abilities && (
<div>
<BasicInfo
name={pokemonInfo.name}
abilities={pokemonInfo.abilities}
/>
</div>
)}
</div>
);
}
What I have tried:
I tried adding state which would change whenever the button is pressed and it’s not used for anything else so it doesn’t matter if it’s true or false. It didn’t fix the problem
2
Answers
useEffect
triggers on the dependency changes, but the initial run is treated as a change as well. If you don’t want to to the fetch untilhasPressed
, wrap the fetch in anif
remove the useEffect, you don’t need it
just trigger the function onSubmit
and get rid of onClick, and add a type="submit" to your button.
you do not need hasPressed state anymore.
Also you don’t need hasInfo state, you can replace "hasInfo && pokemonInfo.abilities" by "pokemonInfo && pokemonInfo.abilities"