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
Стоит ли использовать Redux в Next.js-приложении?

Статья (англ.): https://javascript.plainenglish.io/should-you-use-redux-in-next-js-5e57201c34da

Автор статьи считает, что нам нужно отказаться от Redux в Next.

Причина #1: В нем нет особого смысла, так как благодаря серверному рендерингу мы сразу же, еще до рендеринга страницы, получаем нужные данные.

Причина #2: У Redux есть ряд альтернатив - более легких, нативных и удобных. Например, React Context или Local Storage. В большинстве случаев их функциональности более чем достаточно. Для более сложных сценариев, например, для загрузки данных на клиенте есть библиотеки вроде swr или react-query.

Причина #3: Redux внутри Next сложно хорошо настроить и оптимизировать.

#nextjs #ссылки #redux
👍2
Как настроить Redux в NextJS

Совсем недавно мы видели мнение, что Redux в Next.js использовать не стоит: https://yangx.top/c/1218235935/551

Но если вам все-таки хочется, то вот руководство по настройке (англ.): https://medium.com/how-to-react/how-to-setup-redux-in-nextjs-5bce0d82b8de

Выглядит не особо сложно. Помимо обычных настроек Redux нам понадобится еще функция createWrapper из пакета next-redux-wrapper.

const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);

const wrapper = createWrapper(function() {
return store;
});


Теперь нужно обернуть приложение в провайдер хранилища. Сделать это лучше всего в файле _app.js. В провайдер передаем store.

А чтобы все работало, нужно использовать компонент высшего порядка wrapper.withRedux.

import { Provider } from "react-redux";

function MyApp({ Component, pageProps }) {
return (
Provider store={store}
Component {...pageProps}
)
}

export default wrapper.withRedux(MyApp);


Вот и все, теперь можно пользоваться плюшками Redux.

#nextjs #redux #статьи
👍3