I have some simple lines of code to test the useCallback and setState hook. First I try to write like this:
const App = () => {
const [count, setCount] = useState(0)
const increase = useCallback(() => {
setCount(count + 1) // Passing value to change state
}, [])
console.log(count)
return (
<div id="main">
<h1>Count: {count}</h1>
<button onClick={increase}>Increase</button>
</div>
)
}
export default App;
and then, passing the callback to setCount instead like this:
const App = () => {
const [count, setCount] = useState(0)
const increase = useCallback(() => {
setCount(count => count + 1) // Passing callback
}, [])
console.log(count)
return (
<div id="main">
<h1>Count: {count}</h1>
<button onClick={increase}>Increase</button>
</div>
)
}
export default App;
I know it is weird to use useCallback in this situation, just for some testing. The question is that why I pass the callback to setCount, the Increase button work correctly, whereas the first one will just re-render on the first click
>Solution :
In the first case useCallback closes over the count and at that time count was 0 so It always changes value to 1
So to make it working you should add count dependency to useCallback as:
const increase = useCallback(() => {
setCount(count + 1); // Passing value to change state
}, [count]);
In the second case it is not taking the value from the closure instead it is taking the current value and adds one to it and set the value.
ADDITIONAL INFO
You can use react-hooks/exhaustive-deps eslint rule to know which dependency is missing and tell you how to correct it.