dunnand
dunnand

Reputation: 21

React Beginner - React Components not re-rendering correctly after state update

I am a React beginner and I am trying to create a small game within the browser where an array of numbers is displayed, and the user must correctly choose the sum of all the numbers from a multiple choice selection. I have a button that starts the game via an onClick callback as shown below.

    const [sequence, setSequence] = useState([]);
    const [sum, setSum] = useState(0)
    const [countdown, setCountdown] = useState(10);
    const [multipleChoice, setMultipleChoice] = useState([]);

    const createSequence = () => {
        let newSequence = []
        for (let i = 0; i < 6; i++) {
            newSequence.push(Math.floor(Math.random() * 9) + 1);
        }
        setSequence(newSequence);
    }

    const createRandomAnswers = () => {
        let multipleChoiceArray = someRandomArrayFunction();
        setMultipleChoice(multipleChoiceArray);
    }

    const calculateSum = () => {
        // calculates sum of current number sequence and updates sum state
        let total = 0;
        for (var i in sequence) {
            total += sequence[i];
        }
        setSum(total);
    }

    const createGame = () => {
        createSequence();
        console.log("calculating sum")
        calculateSum();
        createRandomAnswers();
    }

    return (
        <>
            <p> {sum}</p>
            <h2>{sequence}</h2>
            <button onClick={createGame}>Start Game</button>
            <Choice value={multipleChoice[0]} />
            <Choice value={multipleChoice[1]} />
            <Choice value={multipleChoice[2]} />
        </>
    );

These three functions each update state variables using state hooks. However, each correct values of each are not in sync.

For example, if I had an array sequence of [1, 2, 3, 4], the sum should display as 10. When createGame is called, the sequence updates, but the sum does not update until the second time createGame is called, at which point the sequence updates to a new number, and the sum is set to 10.

createGame();
// Sequence displayed as [1, 2, 3, 4]
// sum displayed as 0 (initial state)
// multiple choice displayed as blank (initial state)

createGame();
// Sequence updates to random, e.g. [3, 1, 3, 2]
// sum displayed as 10 (sum from previous sequence)
// multiple choice displayed as blank (initial state)

Why do these values lag behind and update one at a time, when they are all being called within createGame? I know I am probably misunderstanding some core React principle, but any help would be appreciated.

Upvotes: 2

Views: 67

Answers (1)

Mahnoor Ali
Mahnoor Ali

Reputation: 23

This is because useState hooks work asynchronously, meaning that the change does not occur immediately after the setState function is called. If you want that some action 'A' happens immediately after change in state 'total' then you can use useEffect and add a dependency for it such that when XYZ changes(total in your case), setSum(value). Make 'total' as state variable and do these changes:

const [total, setTotal] = useState(0)

const calculateSum = () => {
    // calculates sum of current number sequence and updates sum state
    let total = 0;
    for (var i in sequence) {
        total += sequence[i];
    }
    setTotal(total);
}


 useEffect(() => {
        setSum(total);
         }, [total]);

Upvotes: 2

Related Questions