Home > Blockchain >  useState non-instantaneous updates break function
useState non-instantaneous updates break function

Time:03-14

I have a sumButtonsDict state variable that stores a dictionary of objects. I've also built a simple addSumButton() function add a new object into the sumButtonsDict:

const [sumButtonsDict, setSumButtonsDict] = useState({})

function addSumButton(sum) {
    const dictKey = Object.keys(sumButtonsDict).length
    const sumButtonDict = {
        sum: sum,
        isActive: false
    }
    setSumButtonsDict(prevState => ({...prevState, [dictKey]: sumButtonDict}))
}

As you can see, the function stores every new dictionary item at a key corresponding to the index it's on (e.g., first item has key 0, second item has key 1...), but the correct key is derived from the count of objects already existing in sumButtonsDict.

When the component mounts, I add 5 new buttons using the following:

useEffect(() => {
    addSumButton(10)
    addSumButton(25)
    addSumButton(50)
    addSumButton(100)
    addSumButton(250)
}, [])

but only 1 ends up existing in sumButtonsDict. I suspect this is because setState() doesn't update the state variable immediately, and hence when I call Object.keys(sumButtonsDict).length it keeps on returning 0 even though the addSumButton() has run multiple times before.

How can I get around this?

CodePudding user response:

You're already using the function version of setSumButtonsDict to get the previous state, which is the right thing to do. You just need to move the other bits of code into the function too, so the entire calculation uses prevState:

function addSumButton(sum) {
  setSumButtonsDict(prevState => {
    const dictKey = Object.keys(prevState).length;
    const sumButtonDict = {
      sum: sum,
      active: false,
    }
    return {...prevState, [dictKey]: sumButtonDict}

  });
}
  • Related