---
sidebar_position: 7
---

# Хуки оптимизации и кэширования

useCallback, useMemo, React.Memo (HOC)

## useCallback
`useCallback` — это хук в React, который используется для мемоизации функций. Он помогает оптимизировать производительность компонентов, особенно когда речь идет о передаче функций в дочерние компоненты или их использование в зависимостях других хуков, таких как `useEffect`.

### Зачем нужен useCallback?
1. **Оптимизация рендеринга дочерних компонентов:**
   - В React компоненты перерисовываются, если изменяются их пропсы или состояние.
   - Если вы передаете функцию как пропс в дочерний компонент, и эта функция создается заново при каждом рендере родительского компонента, то дочерний компонент будет перерисовываться даже если это не нужно.
   - `useCallback` позволяет сохранить ссылку на одну и ту же функцию между рендерами, если её зависимости не изменились. Это предотвращает ненужные перерисовки дочерних компонентов.
2. **Избежание лишних вызовов `useEffect`:**
   - Если функция используется в зависимостях `useEffect`, то каждый раз, когда функция создается заново, `useEffect` будет срабатывать снова.
   - useCallback позволяет избежать этого, сохраняя стабильную ссылку на функцию.
3. **Улучшение производительности:**
   - Создание функций в JavaScript — это операция, которая занимает время и память. Если функция не изменяется, то нет смысла создавать её заново при каждом рендере.
   
### Как работает useCallback?
`useCallback` принимает два аргумента:
1. Функция, которую нужно мемоизировать.
2. Массив зависимостей.

Хук возвращает мемоизированную версию функции, которая изменяется только тогда, когда изменяются значения в массиве зависимостей.

### Когда использовать useCallback?
- Когда функция передается в качестве пропса в дочерний компонент, который оптимизирован с помощью `React.memo`.
- Когда функция используется в зависимостях других хуков, таких как `useEffect`.
- Когда создание функции является дорогостоящей операцией.

### Когда не нужно использовать useCallback?
- Если функция не передается в дочерние компоненты или не используется в зависимостях других хуков.
- Если функция простая и её создание не влияет на производительность.

Использование `useCallback` должно быть обоснованным, так как избыточное применение может усложнить код и не принести значительной пользы.

## React.memo
**React.memo** — это функция высшего порядка (Higher-Order Component, HOC), которая используется для оптимизации производительности функциональных компонентов в React. Она позволяет избежать лишних рендеров компонента, если его пропсы не изменились.

### Как работает React.memo?
Когда вы оборачиваете компонент в `React.memo`, React запоминает (мемоизирует) результат его рендеринга. При последующих рендерах React сравнивает текущие пропсы с предыдущими. Если пропсы не изменились, React использует закэшированный результат рендеринга, вместо того чтобы выполнять рендер компонента заново.

### Кастомная функция сравнения:
По умолчанию React.memo поверхностно сравнивает пропсы (с использованием Object.is). Если вам нужно более сложное сравнение, вы можете передать вторым аргументом кастомную функцию сравнения:
```js
const MyComponent = React.memo(
  function MyComponent(props) {
    // Логика компонента
  },
  (prevProps, nextProps) => {
    // Возвращает true, если пропсы считаются равными (рендер не нужен)
    // Возвращает false, если пропсы изменились (рендер нужен)
    return prevProps.value === nextProps.value;
  }
);
```

### Когда использовать React.memo?
1. **Компоненты, которые часто рендерятся с одинаковыми пропсами:**
   - Если компонент часто рендерится, но его пропсы редко меняются, React.memo поможет избежать лишних рендеров.
2. **Тяжелые компоненты:**
   - Если компонент выполняет сложные вычисления или рендерит большое количество элементов, `React.memo` может значительно улучшить производительность.
3. **Компоненты, которые получают стабильные пропсы:**
   - Если пропсы компонента редко меняются (например, данные из контекста или мемоизированные значения), `React.memo` будет полезен.

### Когда не нужно использовать React.memo?
1. **Легковесные компоненты:**
   - Если компонент простой и его рендер не требует значительных ресурсов, использование `React.memo` может быть избыточным.
2. **Компоненты, пропсы которых часто меняются:**
   - Если пропсы компонента часто меняются, `React.memo` не принесет пользы, так как компонент всё равно будет перерисовываться.
3. **Компоненты с побочными эффектами:**
   - Если компонент зависит от побочных эффектов (например, от глобального состояния), `React.memo` может не сработать как ожидается.

### Важные моменты:
- `React.memo` работает только с функциональными компонентами.
- Он не предотвращает рендеры, вызванные изменением состояния внутри компонента.
- Используйте `React.memo` только там, где это действительно необходимо, чтобы не усложнять код без нужды.

## useMemo
Хук `useMemo` в React используется для мемоизации (запоминания) значений. Он позволяет оптимизировать производительность, избегая повторных вычислений значений, которые не изменились между рендерами. Это особенно полезно для дорогостоящих вычислений или операций, которые зависят от определенных данных.

### Как работает useMemo?
useMemo принимает два аргумента:
1. **Функция, которая возвращает значение** (эта функция будет выполнена только при изменении зависимостей).
2. **Массив зависимостей** — список значений, при изменении которых функция будет выполнена заново.

Хук возвращает мемоизированное значение, которое будет пересчитано только при изменении зависимостей.
```js
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
```
### Когда использовать useMemo?
1. **Дорогостоящие вычисления:**
   - Если у вас есть сложные вычисления, которые занимают много времени (например, сортировка больших массивов, математические операции и т.д.), `useMemo` поможет избежать их повторного выполнения.
2. **Оптимизация рендеров:**
   - Если значение используется в рендере компонента и зависит от пропсов или состояния, `useMemo` предотвратит лишние рендеры, если зависимости не изменились.
3. **Передача мемоизированных значений в дочерние компоненты:**
   - Если вы передаете вычисленное значение как пропс в дочерний компонент, `useMemo` поможет избежать лишних рендеров дочернего компонента.

### Когда не нужно использовать useMemo?
1. **Легковесные вычисления:**
   - Если вычисления простые и не требуют значительных ресурсов, использование `useMemo` может быть избыточным.
2. **Часто изменяющиеся зависимости:**
   - Если зависимости часто меняются, `useMemo` не принесет пользы, так как значение будет пересчитываться при каждом рендере.
3. **Не связанные с рендером значения:**
   - Если значение не используется в рендере или не влияет на производительность, `useMemo` не нужен.

### Важные моменты:
- `useMemo` не гарантирует, что функция не будет выполнена. Она может быть вызвана React для "подстраховки" (например, при изменении приоритетов рендеринга).
- Используйте `useMemo` только там, где это действительно необходимо, чтобы не усложнять код без нужды.

🚀 **_Источник: DeepSeek_** \
🚀 **Источник: [YT: memo vs useMemo vs useCallback в React. В чём разница?](https://www.youtube.com/watch?v=l1Byo3u9WGY)**