React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Повторение по селекторам

Статья в документации: https://redux.js.org/usage/deriving-data-selectors

Селекторы - это обычные функции, которые получают на вход состояние приложения (чаще полное состояние, а не отдельные части) и возвращают какие-то данные из него (возможно, обработанные). Например, селектор может возвращать полный список элементов TODO-листа, а может фильтровать его по статусу.

Зачем нужны селекторы

Использование селекторов позволяет сохранять состояние максимально чистым (все, что можно вычислить, вычисляется в селекторах), а также дает возможность переиспользовать логику выбора данных (один селектор можно использовать в нескольких местах). Это особенно удобно, если селектор достает данные из глубин состояния (третий-четвертый уровень вложенности).

В общем, в селекторах инкапсулируется логика получения данных из состояния. Они знают структуру состояния и как достать нужные данные. В идеале, это знание не должно выходить за пределы селекторов и редьюсера. Компоненты не должны заботиться об устройстве состояния, они хотят только получать нужные данные.

Организация селекторов

Документация рекомендует давать функция-селекторам осмысленные имена, начинающиеся с select.

Селекторы обычно располагаются в файлах слайсов, рядом с логикой редьюсера. Отдельные селекторы могут находиться и в компонентах (специфичные селекторы, которые не переиспользуются в других местах). Селекторы также могут находиться внутри thunks, так как там есть доступ к полному состоянию.

Селекторы применяются вместе с хуком useSelector.

Проблемы

Внутри селекторов могут производиться достаточно сложные вычисления, поэтому следует минимизировать количество их запусков. Однако селекторы запускаются при каждом изменении состояния, причем все селекторы, даже те, которые не имеют отношения к изменившимся данным.

Хук useSelector сравнивает результат выполнения селектора с предыдущим (используя строгое равенство `===`). Если значения отличаются, выполняется перерендер. То есть селектор не должен возвращать новое значение, если ничего не изменилось. Но тут появляется проблема, например, с методами массивов (map, filter), которые всегда возвращают новый массив. Даже если список отфильтрованных элементов не изменился, хук увидит новый массив и посчитает, что нужен перерендер.

Чтобы избежать этого, нужна мемоизация селекторов. (Мемоизация не нужна, если селектор возвращает примитивное значение).

Мемоизация

Для мемоизации мы используем библиотеку Reselect (есть и альтернативы, которые указаны в статье). Она предоставляет функцию createSelector, которая принимает любое количество входных селекторов (для проверки изменения различных частей состояния) и один выходной (собственно для выборки данных). Выходной селектор вызывается только в том случае, если входные селекторы возвращают изменившиеся результаты.

#управлениесостоянием #документация #redux #оптимизация
👍3
Реализация функциональности Шаг назад

Статья в документации: https://redux.js.org/usage/implementing-undo-history

В статье описано, как реализовать в Redux-приложении функционал Шаг назад/вперед. В Redux это особенно просто, так как все состояние хранится в одном объекте и при каждом изменении оно представлено новым объектом - значит легко хранить последовательность состояний. К тому же вся логика управления состоянием находится в функции (редьюсере). Здесь можно использовать паттерн декоратор, чтобы добавить новый функционал, не ломая основной.

Глобально паттерн выглядит так:


{
past: [T, T],
present: T,
future: [T]
}


Текущее состояние хранится в поле present. При каждом изменении старое состояние добавляется в массив past, а present изменяется. Если потребуется сделать Шаг назад, мы просто возьмем последнее состояние из past и установим его в present. При этом текущее состояние нужно сохранить в future, чтобы к нему можно было вернуться.

В статье дана полная реализация алгоритма. Также можно воспользоваться готовой реализацией из пакета redux-undo.

#управлениесостоянием #redux #документация #паттерны
👍3