reactjsuse-statereact-functional-component

Should a function always be used for a setState that gets passed an array or object?


Wanting to improve my understanding of React in functional components I've seen some that pass a seState with a function when spreading an array or object. When I reference the docs I see:

Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax

So I'm trying to understand why this implementation:

const [count, setCount] = useState([initialCount]);

setCount([...count, newCount])

is not the preferred when it comes to arrays and objects and this:

const [count, setCount] = useState([initialCount]);

setCount(prevCount => [...prevCount, newCount])

is the preferred. In my research for an answer I haven't found an answer about this and I've read through:

The only conclusions I can establish the need for the function is:

Why when it comes to arrays and objects in a useState it should be passed with a function opposed to what's commonly used?


Solution

  • Its probably best practice to pass a function to the useState dispatch to avoid renders getting out of sync, especially if you use asynchronous methods to update state, but also any time your new state is dependent on previous state (so like even incrementing numbers, not just for objects and arrays).

    As Kent C. Dodds illustrates, there are issues as it comes to closures and the timing of rendering and function calls when the new state update is dependent upon previous state.

    If you want to merge your data with previous state, you want to be sure to merge with the latest state (as of that particular merge call). The setState dispatch provides the previous state as the first parameter. You can be certain that this is the latest state (for that merge) and you won't get out of sync data, or out of order updates.