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
CodePudding user response:
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.
CodePudding user response:
useCallback()
hasn't been used correctly here: the dependencies array should have count
in it. So:
const increase = useCallback(() => {
setCount(count 1) // Passing value to change state
}, [count])
With an empty array as a dependency, it will be memoized for the lifetime of the component and will not update the current count
value.
Source: https://reactjs.org/docs/hooks-reference.html#usecallback
On a side note, using useCallback()
is "overoptimizing" in this case, we are complicating the code while the performance impact to the end users is not noticeable. I would only use it to prevent rerenders in complex views e.g. in a huge list.