简体   繁体   中英

How do I update useState immidiatly for function React

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.

  • Note: "state" in the example is interchangeable with whatever state piece you're dealing with.

Check the documentation for more info.

Either:

  • Pass the new values to selectedWinner as arguments instead of reading from the state.
  • Move the call to 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM