useCallback используется для мемоизации коллбеков в компонентах, а useMemo используется для мемоизации значений. По своей сути, эти два хука ничем не отличаются и предназначение у них одно и тоже - хранение данных. Строение идентичное, как и в useEffect и useLayoutEffect, первым аргументом идёт коллбек и вторым - массив зависимостей.
Вот несколько вопросов:
Зачем использовать два метода для одной цели?
Почему бы просто не вернуть данные или JSX из useCallback и использовать их?
Какая разница между этими двумя методами?

Разница в месте вызова
useMemo вызывается исходниками React'а, а useCallback - нами. Примеры обоих функций:
function memoUsed() { const _ = useMemo(() => { return ‘insert JSX here’ }) return _ } function callbackUsed() { const _ = useCallback(() => { return ‘insert JSX here’ }) return _() }
Вуаля, функция useMemo имитирована очень даже прилично, с помощью вызова коллбека (6 и 14 строки). Одна вещь сделана двумя немного разными способами. Дело в том, что в “память” компоненты при пользовании useMemo попадает значение только из return, игнорируя остальное тело функции. В случае с useCallback - коллбек передаётся как строка, без вызова. Но эта разница не влияет на количество маунтов или рендеров компоненты, записи в плане производительности эквивалентны.
В useMemo не рекомендуется использовать другие хуки
Примерчик:
function memoUsed() { const [state, setState] = useState(null) const _ = useMemo(() => { // причинит бесконечный ре-рендер setState(‘value’) return ‘insert JSX here’ }) return _ } function callbackUsed() { const [state, setState] = useState(null) const _ = useCallback(() => { // обычное дело setState(‘value’) return ‘insert JSX here’ }) return _() }
При вызове постороннего хука в useMemo и сопутствующем изменении состояния компонента приведёт к зацикливанию. Так как useMemo отрабатывает при стадии рендеринга, модификация состояния компонента запустит процесс заново. С useCallback таких проблем нет, функция вызывается по пользовательскому событию.
В useMemo аргумент-функция не принимает параметры
Ближе к делу:
function memoUsed() { const _ = useMemo((arg1) => { // React игнорирует аргументы return ‘insert JSX here’ }, []) return _ } function callbackUsed() { const _ = useCallback((what, where) => { // могут быть использованы в функции return ‘insert ${what} ${where}’ }) return _(‘JSX’, ‘here’) }
По документации для useCallback массив зависимостей обязателен
А для useMemo может являться и undefined, что не совсем точно. При отсутствии массива зависимостей в обоих хуках происходит ре-рендер в ста процентах случаев. Это описание является ошибкой, про что заявлено в комментарии в исходном коде.
// allow undefined, but don't make it optional as that is very likely a mistake
В целом, хук useMemo можно заменить судя по всему и существует лишь для абстрактного отделения мемоизации данных от мемоизации методов. Кто знает, может в дальнейших версиях React'a способы хранения данных будут изменяться, так как это очень похоже на наследие классовых компонентов.