TL;DR: useState is an asynchronous hook and it doesn't change the state immediately, it has to wait for the component to re-render. useRef is a synchronous hook that updates the state immediately and persists its value through the component's lifecycle, but it doesn't trigger a re-render.
React sets its state asynchronously because doing otherwise can result in an expensive operation. Making it synchronous might leave the browser unresponsive. Asynchronous setState calls are batched to provide a better user experience and performance.
useState and setState both are asynchronous. They do not update the state immediately but have queues that are used to update the state object. This is done to improve the performance of the rendering of React components.
(If we wanted to store two different values in state, we would call useState() twice.) What does useState return? It returns a pair of values: the current state and a function that updates it. This is why we write const [count, setCount] = useState() .
You can use useEffect
to access the latest state after updating it. If you have multiple state hooks and would like to track the update on only part of them, you can pass in the state in an array as the second argument of the useEffect
function:
useEffect(() => { console.log(state1, state2)}, [state1])
The above useEffect
will only be called when state1
is updated and you shouldn't trust the state2
value from inside this function as it may not be the latest.
If you are curious about whether the update function created by useState
is synchronous, i.e. if React batches the state update when using hooks, this answer provide some insight into it.
Well, if you refer to the relevant docs you'll find...
const [state, setState] = useState(initialState);
Returns a stateful value, and a function to update it.
During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).
The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
setState(newState);
During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates.
So your new state, whatever it is, is what you've just set in useState
, i.e. the value of initialState
. It goes directly to state
, which updates reactively thereafter. Quoting further from the relevant docs:
What does calling useState do? It declares a “state variable”. Our variable is called count but we could call it anything else, like banana. This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.
If you'd like to do something whenever your state updates, then just use componentDidUpdate
.(docs)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With