I have created a function to calculate the winner between the two selected pokemon. However, instead of using the newly selected option, it is using the previously selected option. It has been brought to my attention that this is because useState is not updating immediately so how would I go about fixing this?
Here is my winner function:
function selectedWinner(){
console.log(pokemonName+' '+pokeOneTotal);
console.log(pokemonName2+' '+pokeTwoTotal);
if(pokeOneTotal>pokeTwoTotal){
setPokemonWinner(pokemonName);
}else if(pokeOneTotal<pokeTwoTotal){
setPokemonWinner(pokemonName2);
}else{
setPokemonWinner("Draw");
}
}
I have set it so that it is called in the different select functions, which are on click functions, here is one as an example:
function optionOneSelected(){
console.log('selected');
axios.get('https://pokeapi.co/api/v2/pokemon/'+ pokemonOne.current.value)
.then((res)=>{
let data=res.data;
console.log(data);
let type = data.types[0].type.name;
let id = data.id;
let height= data.height;
let weight = data.weight;
let name = data.forms[0].name;
let hp = data.stats[0].base_stat;
//console.log(type)
setPokemonType(type);
setPokemonId(id);
setPokemonHeight(height);
setPokemonWeight(weight);
setPokemonName(name);
setPokemonHp(hp);
let sum=0;
sum= data.stats[0].base_stat+ data.stats[1].base_stat+ data.stats[2].base_stat+ data.stats[3].base_stat+data.stats[4].base_stat+data.stats[5].base_stat;
setPokeOneTotal(sum);
let pokemonOneDataList = [
data.stats[0].base_stat, data.stats[1].base_stat, data.stats[2].base_stat, data.stats[3].base_stat,data.stats[4].base_stat,data.stats[5].base_stat
];
let labels = [
'hp', 'Attack', 'Defense', 'Special Attack', 'Special Defense', 'Speed'
];
setPokemonOneData(pokemonOneDataList);
setDataLabels(labels);
selectedWinner();
})
}
You can call useEffect
with pokeOneTotal
and pokeTwoTotal
as dependencies. Whenever pokeOneTotal
or pokeTwoTotal
updates, it will trigger useEffect
useEffect(() => {
if(pokeOneTotal>pokeTwoTotal){
setPokemonWinner(pokemonName);
}else if(pokeOneTotal<pokeTwoTotal){
setPokemonWinner(pokemonName2);
}else{
setPokemonWinner("Draw");
}
}, [pokeOneTotal, pokeTwoTotal])
Setting the state in React acts like an async function.
Meaning that the when you set the state and put a console.log
right after it, it will likely run before the state has actually finished updating.
Which is why we have useEffect
, a built-in React hook that activates a callback when one of it's dependencies have changed.
Example:
useEffect(() => {
// Whatever we want to do after the state has been updated.
}, [state])
This console.log
will run only after the state has finished changing and a render has occurred.
Check the documentation for more info.
Either:
selectedWinner
as arguments instead of reading from the state.selectedWinner
into a separate useEffect
hook that has those state variables as dependencies (so it gets called when, and only when, any of them change).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.