Reputation: 1942
Does it make sense to use useCallback
without deps for simple event handlers?
For example:
const MyComponent = React.memo(() => {
const handleClick = useCallback(() => {
console.log('clicked');
}, []);
const handleOtherClick = () => {
console.log('clicked');
};
return (
<div>
<button onClick={handleClick}>Click me</button>
<button onClick={handleOtherClick}>Click me too</button>
</div>
);
});
What are the pros and cons for using useCallback
in this case?
Upvotes: 30
Views: 29761
Reputation: 1
const useIndependentCallback = <A extends unknown[], R>(callback: (...args: A) => R) => {
const callbackRef = useRef(callback)
callbackRef.current = callback
return useCallback((...args: A): R => callbackRef.current(...args), [])
}
I do this when an independent callback is needed.
Upvotes: 0
Reputation: 23705
Purpose of useCallback
does not depend on if you have dependencies or not. It's to ensure referential integrity. To get better performance. If you need that.
Because for flow having just function or function expression itself make code works well(I mean it does not require us to do any extra action to say referencing actual props etc). So useCallback
is only about performance.
Say we render pure component(instance of React.PureComponent
or functional component wrapped into React.memo
)
function MyComponent() {
const onChangeCallback = ...
return <SomePureComponent onChange={onChangeCallback} />;
}
here if onChangeCallback
is declared as just a function or arrow expression it will be re-created on each render. So it will be referentially different. And nested child will be re-rendered each time while it does not have to.
Another case is listing this callback as dependency in other useCallback
, useMemo
, useEffect
.
function MyComponent() {
const onChangeCallback = ...;
return <Child onChange={onChangeCallback} />
}
...
function Child({onChange}) {
useEffect(() => {
document.body.addEventListener('scroll', onChange);
return () => document.body.removeEventListener('scroll', onChange);
}, [onChange]);
}
Here we also will have referentially different onChange
in Child
without useCallback
. So useEffect
will be run each time parent MyComponent
is called. While we don't need it doing this.
So yes, having empty dependencies list when you don't have actually any dependency is better then declaring function inline without useCallback
at all.
Upvotes: 38