If you are facing the issue of the React useState
not reflecting a change immediately and want to know why this happens and how to fix it, you are on the right page.
In this article, we will discuss the reason behind such behaviour of React’s useState
method and how to fix that.
Why useState set Method Not Reflecting a Change Immediately?
The React state does not update immediately due to the current closure of the state variable, as it is still referring to an old value. To update the state, we need to refresh the state by re-rendering it. And when we re-render the component, a new closure is created that reflects state updates.
const Counter = () =>{
const [counter, setCounter] = useState(0);
const count = () => {
setCounter(counter + 1); //still getting the old value
console.log(counter);
}
return(
<div>
<button onClick={count}>Add</button>
</div>
)
}
Here, we create a counter
state variable and print it using console.log(counter)
, which refers value before the state update as the old closure still holds the old value.
The state updates when React re-renders components because a new closure is created with an updated state value. This cycle happens whenever the state updates.
Does the setState method updates state asynchronously?
Yes, the setState
method updates the state asynchronously, so the state value will not be updated immediately. But this is not the reason behind the state not reflecting changes immediately.
In the example below, we waited 5 seconds after updating state, but we still got the old value. Because the state still belongs to the old closure.
const Counter = () => {
const [count, setCount] = useState(0);
const waitFiveSec = () => new Promise((res) => setTimeout(res, 5000));
const incrementCount = async () => {
setCount(count + 1);
await waitFiveSec();
console.log(`After 5 seconds: ${count}`);
};
return (
<div>
<button onClick={incrementCount}>Add</button>
</div>
);
};
How to reflect state changes immediately?
Using the useEffect
Hook, we can update the state immediately when it changes.
The useEffect
Hook is a powerful tool that allows you to control when and how your components render.
âšī¸ The useEffect
Hook executes after the setState
method has finished processing and updating the state. So using the useEffect
we can control our component state easily.
It accepts two parameters a callback function as its first argument and an array of dependencies as its second argument.
Let’s see how we can use the useEffect
hook.
How to use useEffect hook?
1. Pass a function as a first argument to the hook.
useEffect(() => {
// callback function
}, []);
The function will be called whenever the props or state of the component changes. Inside the function, you can then add whatever custom functionality you need.
For example, if you want to fetch data from an API when the component mounts.
2. Pass the state variable as a dependency array as a second argument to call this hook on state update.
useEffect(() => {
// callback function
}, [state]); // đ dependency array
For example, update the state when the user enters text in the textbox.
const Counter = () => {
const [count, setCount] = useState(0);
const incrementCount = async () => {
setCount(count + 1);
};
useEffect(() => {
console.log(count)
}, [count])
return (
<div>
<button onClick={incrementCount}>Add</button>
</div>
);
};
We passed the state variable age
as a dependency to the useEffect
, so it gets called whenever the age updates. And we get the latest state immediately.
Conclusion
By understanding the behavior of the setState
method and using the useEffect
Hook, we can ensure that the changes to the state are applied immediately.
Learn More:
- Open a Link in a New Tab in React
- Handle Double Click Events in React
- Pass a Component as Props in React
- Component Definition is Missing Display Name in React
- Detect the Browser in React
- Check if a Checkbox is Checked in React
- Format a Number with Commas in React
- Capitalize First Letter of a String in React