Adding useCallback for functions only does something useful if you also React.Memo those children. So while this is a very important optimization, it's not one you need to apply to everything.
If you don't wrap the child component with "React.memo", every time the parent renders the child will render regardless of prop equality, even with memoized props/callbacks.
It only exists/is done to give you a stable reference so you can avoid triggering downstream dependencies (hook arrays and React.memo'd components)
One reason useCallback exists is because useMemo, too, allocates a function on every render- even if it doesn't recompute the underlying value by actually calling the function. So if you're going to be allocating a function anyway, there's no point (performance-wise) to allocating a function that creates a function. You can just cut out the middle-man
The virtual DOM is a tree, and if roughly balanced, the path that needs to be updated is of size log(N) compared to the full tree of size N that will be updated by default.
In practice, it's the difference between a stuttering app that lags at every keypress in an input field, and something usable.