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.
PS if your sub component is not really correct and has memory leak(say useEffect does not return clean-up function) useCallback actually may partially soften consequences. For sure it should not be a goal(to write components with memory leaking) but to me it's 0.5 points for using useCallback even in case of simple handlers