Как использовать useSelector и useDispatch?react-39

Основные понятия

useSelector и useDispatch — это хуки (hooks), предоставляемые библиотекой react-redux для работы с Redux-сторе (хранилищем) в функциональных компонентах.


useSelector

Этот хук позволяет извлекать (select) данные из Redux-стора. Он принимает функцию-селектор и возвращает выбранные данные.

Синтаксис

const result = useSelector(selectorFn, equalityFn?)
  • selectorFn (функция-селектор): Принимает весь стейт (state) и возвращает нужную часть.
  • equalityFn (функция сравнения, опционально): Определяет, нужно ли перерисовывать компонент при изменении данных (по умолчанию используется ===).

Пример

import { useSelector } from 'react-redux';

const CounterComponent = () => {
  const count = useSelector(state => state.counter.value);
  return <div>{count}</div>;
};

Важные нюансы

  1. Ре-рендеры (Re-renders): Компонент перерисовывается при изменении выбранных данных.
  2. Множественные селекторы: Для оптимизации лучше использовать один селектор вместо нескольких.
  3. Мемоизация (Memoization): Для сложных вычислений используйте reselect.

useDispatch

Этот хук возвращает ссылку на dispatch-функцию Redux-стора, чтобы отправлять действия (actions).

Синтаксис

const dispatch = useDispatch();

Пример

import { useDispatch } from 'react-redux';
import { increment } from './counterSlice';

const ButtonComponent = () => {
  const dispatch = useDispatch();
  return <button onClick={() => dispatch(increment())}>+</button>;
};

Лучшие практики

  1. Мемоизация колбэков (Memoizing Callbacks): Если dispatch передаётся в дочерние компоненты, оберните колбэк в useCallback.
    const handleClick = useCallback(() => dispatch(increment()), [dispatch]);
    
  2. Избегайте лишних диспатчей: Не вызывайте dispatch в цикле или условиях без необходимости.

Типичный сценарий использования

import { useSelector, useDispatch } from 'react-redux';
import { decrement } from './counterSlice';

const Counter = () => {
  const count = useSelector(state => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  );
};

Оптимизация производительности

  1. Селекторы с зависимостями (Dependent Selectors):
    const item = useSelector(state => state.items.byId[id], [id]);
    
  2. Использование shallowEqual:
    import { shallowEqual } from 'react-redux';
    const data = useSelector(state => ({ a: state.a, b: state.b }), shallowEqual);
    

Ошибки новичков

  1. Создание объектов в селекторе:

      ❌ Плохо: useSelector(state => ({ value: state.value })) (новый объект при каждом вызове).

      ✅ Хорошо: Выбирайте отдельные значения.

  2. Избыточные диспатчи: Не вызывайте dispatch синхронно после другого dispatch.


Резюмируем

  • useSelector — для чтения данных из стора с подпиской на изменения.
  • useDispatch — для отправки действий.
  • Оптимизируйте с помощью memo, useCallback и shallowEqual.