reactjsreact-16

Handling out of date state in functional components


I am running into issues setting a state created with the 'useState' hook from within async functions.

I've created a codepen to demonstrate: https://codepen.io/james-ohalloran/pen/ZdNwWQ

const Counter = () => {
  const [count, setCount] = useState(0);

  const increase = () => {
    setTimeout(() => {
      setCount(count + 1);
    },1000);
  }

  const decrease = () => {
    setTimeout(() => {
    setCount(count - 1);
    },1000)
  };
  return (
    <div className="wrapper">
      <button onClick={decrease}>-</button>
      <span className="count">{count}</span>
      <button onClick={increase}>+</button>
    </div>
  );
};

In the above example, if you click 'increase' followed by 'decrease'..you will end up with -1 (I would expect it to be 0). If this was a React class instead of a functional component, I would assume the solution would be to use bind(this) on the function, but I didn't expect this to be an issue with arrow functions.


Solution

  • Ah, I found a solution. I didn't realize I'm able to reference the previousState from the useState setter function: https://reactjs.org/docs/hooks-reference.html#functional-updates