I'm using useCallback
to memoize a function, I wrote 2 functions, formatCounter
and formatCounter2
and added useCallback
to the functions with dependencies of counter
and counter2
.
When onClick
function is called, the counter
variable has changed but formatCounter2
called, but why? As I understand it needs to be called only when the dependency changes (counter2
) and it does not change.
function App() {
const [counter, setCounter] = React.useState(0);
const [counter2, setCounter2] = React.useState(0);
const onClick = React.useCallback(()=>{
setCounter(prevState => ++prevState)
},[]);
const onClickSecond = React.useCallback(()=>{
setCounter2(prevState => ++prevState)
},[]);
const formatCounter = React.useCallback((counterVal)=> {
console.log('formatCounter Called')
return `The counter value is ${counterVal}`;
},[counter])
const formatCounter2 = React.useCallback((counterVal2)=> {
console.log('formatCounterTwo Called')
return `The counter value2 is ${counterVal2}`;
},[counter2])
const objMemo = React.useMemo(()=> {
console.log('obj memo is')
return {
a:counter>2?'counter is bigger than 2': 'counter is less than 2'
}
},[counter])
return (
<div className="App">
<div>{formatCounter(counter)}</div>
<div>{formatCounter2(counter2)}</div>
<button onClick={onClick}>
Increment
</button>
<button onClick={onClickSecond}>
Increment2
</button>
<p>{objMemo.a}</p>
</div>
);
}
useCallback
memoizes the function reference. But you're calling the format functions (both) in the render method. So what you're actually seeing is the inner function being called.
Maybe out of curiosity you can check the reference to the function you're memoizing. There you will see that the reference is not changing.
To check this I usually do:
useEffect(() => {
console.log('formatCounter reference changed!', formatCounter);
}, [formatCounter]);
You will see that it logs for when counter
changes but not for when counter2
changes.