FAQ: The State Hook - Set From Previous State

By using the useState hook, a lot of things pertaining to state are handled for us.
For example,

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

This is initializing the state of count to 0 and also giving us a means of changing state via the setCount state setter. The initial value of the state can be chosen to be a number, string, boolean, array, object, whichever is appropriate.
Under the hood away from our sight, the state setter setCount has been implemented in such a way that it can be used in two ways. We could a) pass a value to the state setter or b) pass a function to the state setter. The state setter is able to recognize whether it has been passed a value or a function.
a) If simply a value is passed to the state setter, then it replaces the old state with the new state.

const [count, setCount] = useState(0);
// ...
setCount(13); 
// This will overwrite the state of count.
// 0 will be replaced by 13.

b) The second way to use a state setter is by passing it a function. The state setter is able to distinguish between a value and a function. This function is expected to return some value, which will then be used by the state setter to set the new state. To make things easy for us, if the function has a parameter, then the state setter will automatically pass the previous state as an argument. We don’t have to worry about explicitly providing the previous state to the state setter. It will be taken care for us. We can name our parameter whatever we want. The state setter will recognize that it has been passed a function with a parameter, so it will automatically assign the previous state to this parameter. When we want to preserve the existing old value or want to use the old value in some calculation to arrive at a new value, then this approach allows us that flexibility.

// Suppose the current count is 13

setCount(prevCount => prevCount + 1);
// setCount will recognize that this is a function. 
// It will automatically pass 13 as the argument and assign it to prevCount.
// The arrow function increments the previous count by 1.
// An implicit return of 14 is made. setCount then sets count to be 14.
// If we had more than one statement in the body of the arrow function,
// we could use curly braces and then do an explicit return of the new value.

In our case, we have picked prevCount as the parameter name. There is nothing special about the name prevCount. We could have picked a different name, but prevCount is a good choice as it reminds us of the word previous. We could have picked abc as the parameter name, but that would be a poor choice in terms of readability. We should pick names that help the reader understand the code, rather than picking random names.
In the documentation, see
https://reactjs.org/docs/hooks-reference.html#functional-updates

const increment = () => setCount(prevCount => prevCount + 1);

is correct. setCount is responsible for providing and assigning the previous state to prevCount. Not our responsibility.

8 Likes