import React, { useState, useEffect } from 'react'
function Counter() {
const [count, setCount] = useState(0)
const incCount = () => {
console.log("count ", count)
// setCount(count + 1)
setCount(x => x + 1)
}
useEffect(() => {
console.log('use effect called')
const intervalId = setInterval(() => incCount(), 1000)
return() => {
// clearInterval(intervalId);
console.log("clear interval called")
}
}, [])
return (
<div>
{count}
</div>
)
}
export default Counter
In display count
is increasing as expected but in console every time it shows 0 only. incCount
is executing after every one second and in console count
0 is printing is whereas on screen count
is increasing by 1 every time as expected.
2
Answers
In your React component, the incCount function is using the count variable from its initial render, which remains constant at 0 in the console log. The setCount call updates the state correctly, so the displayed count increments as expected, but since the count variable inside incCount doesn’t update between renders, it logs 0 every time.
To see the updated count in the console each time incCount is called, you should log the count state within the setCount callback function. Here’s how you can modify your code to achieve that:
In this updated code, the console.log statement is placed inside the setCount callback, which receives the most recent state value (prevCount). This ensures that the console logs the updated count each time incCount is called.
The
useEffect
hook is running as expected, there’s no issue there.The issue you have is that of a stale Javascript Closure over the
count
state in theincCount
function scope that is passed to thesetInterval
callback.setInterval
gets that initial instance "copy" ofincCount
that it just calls repeatedly each interval. I never gets a new copy with the updatedcount
state value closed over in scope.Methods to address:
Use a
useEffect
hook to console log thecount
state when it updates. This is the simplest and most trivial.Use a React ref to cache the
count
state that can be referenced from the closure.Note
While you could
console.log
the currentcount
state value in thesetCount
state updater functionand there’d be no adverse reaction since
console.log
is rather benign, you should be aware this is not recommended as the state updater functions are to be considered pure synchronous functions, and technically speaking logging the value is a side-effect and should be avoided.