0
import "./styles.css";
import {useState} from 'react';

export default function App() {

  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  console.log("Render: ", count, count2);

  function update() {
    setCount(count + 1);
    setCount(count + 1);
  }

  function updateWithCB() {
    setCount2(prevCount => prevCount + 1);
    setCount2(prevCount => prevCount + 1);
  }

  return (
    <div className="App">
      <p>{count}</p>
      <button onClick={update}>+</button>
      <br />
      <p>{count2}</p>
      <button onClick={updateWithCB}>+ with CB</button>
    </div>
  );
}

I am a learning react and came across this behavior. When + is clicked it updates only once but when + with cb is clicked, it updates twice as intended. Does that mean useState function calls are merged and if so how to predict the merging when multiple useState calls are in use? And why doesn't it print 2 when + button is clicked once as it should? Any react specific reasons? Thanks

Vegeta
  • 461
  • 2
  • 6
  • 1
    In `updateWithCB` you are adding up prev count so once first function `setCount2(prevCount => prevCount + 1);` run the count has been updated so for second time you run the count value in `prevCount` is 1 so it updates to 2. But in `update()` function prevCount is not tracked thus it gives 1. – Nithin - Techidiots May 04 '21 at 12:53
  • For more clarification check out https://stackoverflow.com/a/54807520/11727479 – Nithin - Techidiots May 04 '21 at 12:55

2 Answers2

2

Since the setState batches the previous setStates will be overridden by the last setState in this case (in the update-function), therefore you need to use the functional setState as you use in updateWithCB.

Take a look at this answer, I think its pretty clear: What is prevState in ReactJS?

Martin Z
  • 238
  • 2
  • 5
1

Basically, this is what happens inside yourupdate function: setCount(0 + 1); setCount(0 + 1);

So, at the end you have count set to 1. But when you use the callback way it works as you expect it to: the state updates async, all callbacks are passed the actual state value.(prevCount in your case).