skip to Main Content

I am building a Tenzies game and would like to implement a functionality that stores the number of previous rolls of the dice a user has to the localStorage and I already have a feature that renders the number of current rolls to the UI.

What I initially did was get a count that increases when the roll button is pressed. The rollCount saves the number of rolls. prevRollCount stores the previous count which should be the value of rollCount. The issue is the storeRoll which console logs the value I intended first then almost immediately logs undefined after setting the storeRoll to zero on page refresh. The undefined is logged until there is a win. Then the value of storeRoll updates to the previous roll count as intended but on subsequent gameplay without page refresh, it adds the number of rolls to the previous roll.

On refresh, it outputs the stored value and then immediately logs undefined again and the loop continues as mentioned above.

    const [tenzies, setTenzies] = useState(false);

    let [rollCount, setRollCount] = useState(0);

    const [prevRollCount, setPrevRollCount] = useState(rollCount);

    const [storeRoll, setStoreRoll] = useState(JSON.parse(localStorage.getItem("die"))
    );

Actually using a useEffect() and storing the code to retrieve in a state. Didn’t include a dependency array because that enabled the storeRoll to be updated after discovering a win. tenzies is updated in another useEffect to true on a win.

     useEffect(() => {
       setStoreRoll(localStorage.setItem("die", JSON.stringify(prevRollCount))
       ); 

         if (tenzies) {
           setStoreRoll(prevRollCount);
         }
     });
  
     // Updates the roll count back to zero when there is a win
     function updateRollCount() {
        setTenzies(false);
        setDice(allNewDice([1, 2, 3, 4, 5, 6]));
        setRollCount(0);
        setTime(0);

        if (prevRollCount !== rollCount) {
          setStoreRoll(prevRollCount);
        }
     }

     // Saves the state of the dice we held or do not want to change on roll
      function rollDice() {
        if (!tenzies) {
          setDice((prevValue) => {
            return prevValue.map((die, index) => {
              return die.isHeld
                ? { ...die }
                : (die = allNewDice([1, 2, 3, 4, 5, 6])[index]);
            });
          });      
         } 

        else {
          setTenzies(false);
          setDice(allNewDice([1, 2, 3, 4, 5, 6]));
        }

        // Updates state for the number of rolls
        setRollCount(prevValue => 
          prevValue + 1
        );

        setPrevRollCount(prevValue => prevValue + 1);

     }

`

What I basically want to do is that when a user wins a game and starts a new game, initialize a new state that helps store that value showing them their previous roll.

Here is the link to an updated Sandbox demo

2

Answers


  1. Chosen as BEST ANSWER

    I figured out the issue. It was because I was trying to get the value of storeRoll without checking whether it exists first.


  2. The reason you are seeing undefined when console logging the prevRolls state right after setting it is due to React state updates being asynchronous. Setting state via setPrevRolls() will trigger a re-render, but the new state value won’t be available immediately.

    There are a couple ways to fix this:

    1. Use the callback form of setState:
    setPrevRolls(prevRollsFromLocalStorage, () => {
      console.log(prevRolls) // will have updated value
    })
    
    1. Use useEffect to run code after state has updated:
    useEffect(() => {
      console.log(prevRolls) 
    }, [prevRolls])
    
    1. Access prevRolls later after component re-renders, such as in rendered UI.

    The issue is React hasn’t finished updating prevRolls when you try to log it immediately after setting. Use a callback, useEffect, or access later in component lifecycle to get the updated value.

    Identifying the asynchronous state update behavior as the root cause is key to solving issues like this in React.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search