Как работает useCallback и для чего он используется?react-25

useCallback — это хук (hook) в React, который предназначен для мемоизации (запоминания) функций между рендерами компонента. Он помогает оптимизировать производительность, предотвращая ненужные ререндеры дочерних компонентов.

Основной принцип работы

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b], // Массив зависимостей (dependencies)
);
  1. Мемоизация функции:
    useCallback возвращает одну и ту же функцию (по ссылке) между рендерами, если зависимости (dependencies) не изменились.
    Если зависимости изменились — создаётся новая функция.

  2. Массив зависимостей:
    Второй аргумент — это массив значений, при изменении которых функция будет пересоздана. Если массив пуст ([]), функция создаётся только один раз (при монтировании).

Для чего используется?

  1. Оптимизация дочерних компонентов:
    Полезен, когда вы передаёте колбэки (callbacks) в дочерние компоненты, особенно в React.memo или PureComponent. Без useCallback при каждом рендере родителя будет создаваться новая функция, что приведёт к ререндеру дочернего компонента, даже если его пропсы (props) не изменились по содержимому.

    Пример:

    const Child = React.memo(({ onClick }) => {
      console.log('Child render');
      return <button onClick={onClick}>Click</button>;
    });
    
    function Parent() {
      const [count, setCount] = useState(0);
      const handleClick = useCallback(() => {
        console.log('Button clicked');
      }, []); // Функция не пересоздаётся
      return (
        <>
          <Child onClick={handleClick} />
          <button onClick={() => setCount(count + 1)}>Ререндер родителя ({count})</button>
        </>
      );
    }
    

    Здесь Child не будет ререндериться при клике на кнопку в Parent, так как handleClick остаётся той же функцией.

  2. Зависимости в эффектах (Effects):
    Если функция используется в useEffect, её мемоизация через useCallback помогает избежать лишних срабатываний эффекта.

Когда НЕ нужно использовать useCallback?

  1. Для простых компонентов: Если компонент и так рендерится быстро, оптимизация может быть избыточной.
  2. Если нет проблем с производительностью: Преждевременная оптимизация усложняет код без необходимости.

Разница между useCallback и useMemo

  • useCallback мемоизирует функцию, а useMemoрезультат вычислений.
    Пример:
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    

Резюмируем

  • useCallback запоминает функцию между рендерами, пока не изменятся её зависимости.
  • Основная цель — оптимизация производительности за счёт предотвращения ненужных ререндеров.
  • Используйте его осознанно, только когда это действительно необходимо.