I’m a beginner in React.js, and I was reading this article:
https://blog.logrocket.com/solve-react-useeffect-hook-infinite-loop-patterns/
There, there’s this code:
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount((count) => count + 1);
}, []);
return (
<div className="App">
<p> value of count: {count} </p>
</div>
);
}
This is the code from the site, to which I’ve added the dependency array.
It shows a useEffect code that should print the value of 1 on the screen.
However, here on my side the printed value is 2.
Also, if I try the following (same code, but logging "count" value to the console):
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount((count) => count + 1);
}, []);
useEffect(() => {
console.log(count);
}, [count]);
return (
<div className="App">
<p> value of count: {count} </p>
</div>
);
}
The logged values are 0, 0 and 2. What explains this weird behaviour? Shouldn’t it just print the value of 1 in the console (first useEffect triggers once, followed by the second useEffect triggering once?)?
2
Answers
The "weird" behaviour was being caused by Strict Mode.
The behavior you’re observing is due to how the useState and useEffect hooks work in React. Let’s me break down the code for your understanding:
In your first example
The useEffect with an empty dependency array [] is executed after the initial render, and it increments count by 1. This means that count should be 1 after the first render. However, since the setCount function is asynchronous, it doesn’t immediately update the value of count inside the same render cycle. So, you see 0 during the render, and after the update, it becomes 1.
In your second example:
The first useEffect runs as before and sets count to 1. The second useEffect has a dependency on count, so it logs the current value of count, which is 0, after the first render. Then, since count changes, it logs the updated value, which is 2, after the second render.
In both cases, count is correctly updated to 1, but it’s only reflected in the component’s render after the initial render. This behavior is due to the asynchronous nature of state updates in React.
If you want to ensure that the updated count is logged immediately after it’s incremented, you can use the useEffect with an empty dependency array for logging, like this:
In this way, it will log the updated value immediately after the state change.