React Asynchronous useState Hook - Part 2

Published on
3 mins read
––– views

In part 1, we discovered why useState hook doesn't update immediately and how could we overcome that. You can read it here

What if it's a function?


On part one, we looked at a simple problem, but what if we need to deal with a function?

In this example, we will dive into a different problem.

What do we have?


Here we setup 3 useState hooks, each has a different default value useState(NUMBER). When the button is pressed, they increment by 1, 2 and 3. After that, just to keep things simple, we output updated values via window.alert.

function Multiply() {
  // each has different default value
  const [addOne, setAddOne] = useState(1);
  const [addTwo, setAddTwo] = useState(2);
  const [addThree, setAddThree] = useState(3);

  function addValues() {
    // if button is clicked, current value increases.
    setAddOne(addOne + 1);
    setAddTwo(addTwo + 2);
    setAddThree(addThree + 3);

    // alerting the user
    window.alert(`
    Here are the new numbers:
    Add One: ${addOne}
    Add Two: ${addTwo}
    Add There: ${addThree}
    `);
  }

  return (
    <div>
      <button onClick={addValues}>Add numbers</button>
    </div>
  );
}

Alright, imagine clicking on the button and seeing the alert. What numbers would we see?

If you read the part 1, you would know that, we will get 1, 2 and 3, Instead of 2, 4 and 6.

Our window.alert is showing old values to the user. On this example, it not a big deal, the user can click one more time to get next values but it's always going to be one render behind. In a real world application, outputting old values as new can cause problems.

How can we fix that?


Here is the solution:

function addValues() {
  // we don't need these anymore
  //
  // setAddTwo(addTwo + 2)
  // setAddOne(addOne + 1)
  // setAddThree(addThree + 3)
  //
  // above code is replaced with this
  const nextOne = addOne + 1;
  const nextTwo = addTwo + 2;
  const nextThree = addThree + 3;

  // we need to update our setters
  setAddOne(nextOne);
  setAddTwo(nextTwo);
  setAddThree(nextThree);

  // we don't use addOne, addTwo... anymore
  // we need to replace them with nextOne... so on
  window.alert(`
    Here are the new numbers:
    Add One: ${nextOne}
    Add Two: ${nextTwo}
    Add There: ${nextThree}
    `);
}

On part 1, we declared a new value nextValue inside the onClick event, on part 2, we did the same thing inside a function. Because we had multiple hooks to deal with at once.

Working principle is the same:

  1. We set our default values with setState(NUMBER)
  2. We declare new variable, nextValue
  3. On click, current value updates with another number, like currentValue + 1,
  4. We save the updated value to nextValue
  5. We call the setter, setValue, with the nextValue.
  6. React renders the current value, not the previous render.

And that is pretty much it.