useCallback without useMemo on the child achieves nothing

Memoising a callback stops it changing identity between renders, which only matters if something downstream is comparing identities — and by default nothing is.

// pointless on its own: Row re-renders regardless
const onSelect = useCallback(id => setSelected(id), []);
return rows.map(r => <Row key={r.id} row={r} onSelect={onSelect} />);

// this is what makes it do something
const Row = React.memo(function Row({ row, onSelect }) { /* ... */ });

The two have to be introduced together or the useCallback is pure overhead — it allocates and compares an array on every render to avoid an allocation that was not costing anything. The other legitimate use is when the function is itself a dependency of an effect, where a changing identity causes a re-subscription rather than a re-render. Reaching for either without measuring is the most common form of premature optimisation in a React codebase.