← Назад к вопросам

Как работает UseSelector?

2.0 Middle🔥 152 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Принцип работы useSelector в Redux Toolkit

useSelector — это хук React Redux, который позволяет компонентам извлекать и подписываться на определенные части состояния из хранилища Redux. Его работа основана на нескольких ключевых механизмах, обеспечивающих эффективность и реактивность.

Основная функция

useSelector принимает селекторную функцию, которая получает всё состояние Redux и возвращает необходимую его часть. При каждом изменении состояния в хранилище хук повторно выполняет селектор, и если возвращаемое значение изменилось (согласно строгому сравнению ===), компонент перерисовывается.

import { useSelector } from 'react-redux';

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

Ключевые механизмы работы

  1. Подписка на хранилище
    При монтировании компонента useSelector подписывается на Redux-хранилище. Когда действие (action) диспатчится и состояние обновляется, хранилище уведомляет все подписанные компоненты.

  2. Выполнение селектора
    После уведомления хук выполняет переданную селекторную функцию с текущим состоянием. Он кэширует предыдущий результат селектора для сравнения.

  3. Сравнение результатов (equality check)
    По умолчанию используется строгое сравнение (===) между предыдущим и новым результатами селектора. Если значения отличаются, компонент помечается для повторного рендеринга. Можно передать функцию сравнения вторым аргументом:

    const user = useSelector(
      state => state.user,
      (prev, next) => prev.id === next.id && prev.name === next.name
    );
    
  4. Батчинг обновлений
    React Redux использует батчинг (отложенное обновление) через ReactDOM.unstable_batchedUpdates(), чтобы несколько диспатчей в одном событийном цикле вызывали только один ре-рендер.

  5. Отписка при размонтировании
    При уничтожении компонента автоматически удаляется подписка на хранилище, предотвращая утечки памяти.

Особенности производительности

  • Селекторы должны быть чистыми — для одинаковых входных данных возвращать одинаковый результат.

  • Мемоизация селекторов — с помощью createSelector из Reselect:

    import { createSelector } from '@reduxjs/toolkit';
    
    const selectUserData = createSelector(
      [state => state.user],
      user => ({ name: user.name, age: user.age })
    );
    
    const userData = useSelector(selectUserData);
    

    Мемоизированные селекторы кэшируют результаты, предотвращая лишние вычисления.

  • Избегание создания новых объектов в селекторе при каждом вызове:

    // Плохо — новый массив при каждом вызове
    const items = useSelector(state => state.items.filter(item => item.active));
    
    // Лучше — мемоизированный селектор или селектор в слайсе
    const activeItems = useSelector(state => state.items.activeItems);
    

Отличия от connect()

useSelector предоставляет более декларативный подход по сравнению с connect():

  • Не требует оборачивания компонента в HOC
  • Позволяет выбирать несколько частей состояния в одном компоненте
  • Упрощает чтение кода и тестирование
  • Позволяет использовать несколько вызовов useSelector для разных частей состояния

Под капотом

React Redux использует Context API для предоставления хранилища. Однако вместо прямого использования контекста для состояния, он передает только ссылку на хранилище. Подписка осуществляется напрямую на Redux store, что обеспечивает оптимизацию и предотвращает лишние ре-рендеры.

useSelector интегрирован с механизмом подписок React Redux v7+, который использует «паттерн наблюдателя» для эффективного обновления только затронутых компонентов.

Этот хук стал стандартом для работы с Redux в функциональных компонентах, сочетая простоту использования с оптимизированной производительностью благодаря грамотной реализации подписок и сравнений.