0

I want all these setState functions to run synchronously because as you can see, the functions running next to it depends on some of the value and it would produce the wrong result if the value is not updated. I have tried many solutions like turning it into a promise but even that is not working and I have no idea why. I have read many blogs and the documentation, yet it is not helping.

function handleClick(userInput) {
        setRandomNumber(generateRandomNumber());
        setUserInputNumber(userInput);
        setResult(findWinner(userInput, randomNumber));

        if (result === "win") setUserScore((prevScore) => prevScore + 1);
        if (result === "lose") setComputerScore((prevScore) => prevScore + 1);
    }

These are the implementation using useEffect hook:

useEffect(() => {
        console.log("computer choice", randomNumber);
        console.log("matchesPlayed", matchesPlayed);
        setResult(findWinner(userInputNumber, randomNumber));
    }, [matchesPlayed]);

    useEffect(() => {
        console.log(result);
        if (result === "win") setUserScore((prevScore) => prevScore + 1);
        if (result === "lose") setComputerScore((prevScore) => prevScore + 1);
    }, [result]);

But it is not still working because the second useEffect hook is not re-rendering if the result is the same as before. But I need it to update it every time the match is played because if it is not re-rendering on the same result, then the score will not be updated for consecutive wins or losses. So the way I want the code to work is like this:

useEffect(() => {
        console.log("computer choice", randomNumber);
        console.log("matchesPlayed", matchesPlayed);
        setResult(findWinner(userInputNumber, randomNumber));
    }, [matchesPlayed]);

    useEffect(() => {
        console.log(result);
        if (result === "win") setUserScore((prevScore) => prevScore + 1);
        if (result === "lose") setComputerScore((prevScore) => prevScore + 1);
    }, [matchesPlayed]);

But, since it is updating simultaneously because the dependencies are the same, then the setResult is running asynchronously and is not updating the state of the result variable.

Please leave your solutions

  • If you have complex coupled logic due to state, then you can look for [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer) hook. – user1672994 Jun 20 '22 at 12:30

1 Answers1

0

The easiest way I see is to reset result on second useEffect in this way:

    useEffect(() => {
        console.log("computer choice", randomNumber);
        console.log("matchesPlayed", matchesPlayed);
        setResult(findWinner(userInputNumber, randomNumber));
    }, [matchesPlayed]);

    useEffect(() => {
        console.log(result);
        if (result === "win") setUserScore((prevScore) => prevScore + 1);
        if (result === "lose") setComputerScore((prevScore) => prevScore + 1);
        if (result != "") setResult("");
    }, [result]);

The thing I don't like in this solution is that second useEffect will be called 2 times: first time on setResult(findWinner(userInputNumber, randomNumber)); and second time in setResult("");.

Giovanni Esposito
  • 10,696
  • 1
  • 14
  • 30
  • It's working bro, great. But the problem is since I am resetting the result to " ", the message is not printed out about the result as the message depends on the value of the result – Areebuddin Phundreimayum Jun 20 '22 at 13:06
  • Do you have any solutions to this? – Areebuddin Phundreimayum Jun 20 '22 at 13:06
  • @AreebuddinPhundreimayum you could launch message on second `useEffect` after you `setUserScore` or `setComputerScore` just before reset `result`. Inside the 2 ifs. something like : `if (result === "win") {setUserScore(...); setMessage("user won")}` – Giovanni Esposito Jun 20 '22 at 13:09