Don’t worry about it
Don’t worry about creating new functions on each render. Only in edge cases does that impede your performance.
Setting onClick
handlers are not one of those, so just create a new function on each render.
However, when you need to make sure you use the same function every time, you can use useCallback
Why not use useCallback
for onClick
Here is a reason why you shouldn’t bother with useCallback
for onClick
handlers (and most other event handlers).
Consider the following code snippets, one without useCallback:
function Comp(props) {
return <button onClick={() => console.log("clicked", props.foo)}>Text</Button>
}
and one with useCallback:
function Comp(props) {
const onClick = useCallback(() => {
console.log("clicked", props.foo)
}, [props.foo])
return <button onClick={onClick}>Text</Button>
}
The only difference in the latter is that React doen’s have
to change the onClick
on your button if props.foo
remains the same.
Changing the callback is a very cheap operation, and it’s not at all
worth complicating your code for the theoretical performance improvement it gives.
Also, it’s worth noting that a new function is still created on every render
even when you use useCallback
, but useCallback
will return the old one
as long as the dependencies passed as the second argument are unchanged.
Why ever use useCallback
The point of using useCallback
is that if you compare two functions with reference
equality, fn === fn2
is true only if fn
and fn2
point to the same function in memory.
It doesn’t matter if the functions do the same.
Thus, if you have memoisation or otherwise only run code when the function changes,
it can be useful to use useCallback
to use the same function again.
As an example, React hooks compare old and new dependencies, probably using Object.is.
Another example is React.PureComponent, which will only re-render when props or state have changed. This can be useful for components that use a lot of resources to render. Passing e.g. a new onClick
to a PureComponent on each render will cause it to re-render every time.