How to Properly Set Multiple States Inside Multiple useEffect Hooks in React


Suppose we have a state that we’ve initialized using useState().

const [ count, setCount ] = useState({
  a: 0,
  b: 0
});

Suppose we want to update multiple attributes inside count using different useEffect() hooks.

We might think to write it this way.

useEffect(() => {
  setCount({ ...count, a: props.a });
}, [props.a]);

useEffect(() => {
  setCount({ ...count, b: props.b });
}, [props.b]);

The problem with this approach is that a may never be updated.

Both useEffect() hooks run in the same React cycle and the same context. This means that the value of a and b inside ...count is exactly the same in both useEffect() hooks. The second setCount() will inevitably replace the first setCount().

In order to solve this problem, we can do this instead:

useEffect(() => {
  setCount((count) => ({ ...count, a: props.a }));
}, [props.a]);

useEffect(() => {
  setCount((count) => ({ ...count, b: props.b }));
}, [props.b]);

After each setCount(), we will receive the most updated value of count.