Redux без createStore и connect: современный путь для новичка

Redux остаётся библиотекой для предсказуемого управления общим состоянием, но подход к ней заметно изменился после 2023 года. createStore считается устаревшим API, а в выпуске React Redux 9.3.0 команда пометила connect как устаревший и закрепила хуки useSelector и useDispatch как современный способ работы с React — это зафиксировано в официальном журнале выпусков React Redux.
Основы при этом прежние: состояние хранится централизованно, события описываются действиями, а новое состояние вычисляют редукторы. Новичку полезно понимать эту модель, но применять её следует через Redux Toolkit — набор инструментов, который сокращает ручную настройку и помогает избежать типичных ошибок с неизменяемостью данных.
Какую проблему решает Redux
Redux организует данные, которые нужны нескольким частям приложения и должны изменяться по единым правилам. Это может быть содержимое корзины, активная учётная запись, параметры сложного редактора или состояние многоэтапного рабочего процесса.
Локальное состояние хорошо работает, пока данными владеет один компонент или небольшая связанная группа компонентов. Сложность появляется, когда одно значение читают и меняют разные экраны, обновления приходят из нескольких мест, а причину текущего результата трудно восстановить.
Redux выносит такие данные в отдельное хранилище. Компоненты читают необходимые значения, но не переписывают их произвольно: изменение проходит через заранее описанное событие и соответствующую логику обновления.
Централизация не означает, что в Redux нужно переносить всё. Значение простого поля, состояние наведённого указателя или открытие одного выпадающего меню обычно удобнее оставить внутри компонента. Хранилище оправдано для разделяемых и относительно долговечных данных, а не для каждой детали интерфейса.
Из чего состоит модель Redux
Хранилище содержит текущее дерево состояния приложения. Обычно оно разделено на предметные области, или срезы: например, сеанс пользователя, корзину и настройки редактора.
Действие — объект, описывающий произошедшее событие. Хорошее название действия сообщает о факте: товар добавлен, фильтр выбран, загрузка завершена. Само действие не определяет весь способ изменения данных, а передаёт информацию редуктору.
Редуктор получает прежнее состояние и действие, а затем вычисляет следующее состояние. Он должен оставаться предсказуемой функцией: сетевые запросы, таймеры и другие побочные эффекты размещают за его пределами.
Условный пример — корзина интернет-магазина. Нажатие кнопки отправляет действие добавления товара, редуктор обновляет срез корзины, после чего счётчик в шапке и страница заказа получают новое значение из одного хранилища. Промежуточным компонентам не приходится передавать эти данные через длинную цепочку свойств.
Почему новый код начинают с Redux Toolkit
Классические учебные примеры часто требуют вручную объявлять строковые типы действий, писать отдельные создатели действий, объединять редукторы и вызывать createStore. Эти конструкции помогают понять внутреннюю механику, но больше не являются рекомендуемой отправной точкой.
Redux Toolkit предоставляет configureStore для создания хранилища и createSlice для описания отдельной области состояния. createSlice объединяет начальное значение и функции обновления, а типы и создатели действий формирует автоматически. Внутри такого редуктора допустим код, похожий на прямое изменение объекта: встроенный Immer преобразует его в неизменяемое обновление.
configureStore добавляет стандартные проверки, промежуточное программное обеспечение и подключение к инструментам разработчика. Актуальная страница официального пакета Redux Toolkit называет его рекомендуемым набором для разработки на Redux и предлагает готовые шаблоны для новых приложений на React.
Redux Toolkit не отменяет действия и редукторы, а даёт более компактный способ их описания. Поэтому знания старой модели остаются полезными для чтения существующего кода, но копировать её многословный синтаксис в новый проект обычно не требуется.
Как Redux соединяется с React
Redux не является частью React и может работать независимо от него. Для интеграции используется отдельная библиотека React Redux: Provider делает хранилище доступным дереву компонентов, useSelector читает выбранные данные, а useDispatch отправляет действия.
- Определите данные, которыми действительно должны пользоваться разные части приложения.
- Опишите соответствующие срезы через createSlice.
- Соберите их редукторы в configureStore.
- Передайте хранилище приложению через Provider.
- Читайте значения через useSelector и отправляйте действия через useDispatch.
Селектору лучше возвращать только то значение, которое нужно конкретному компоненту. Если без необходимости извлекать всё корневое состояние или при каждом вызове создавать новый объект, компонент может обновляться чаще, чем требуется.
Производные данные обычно не нужно сохранять второй копией. Например, количество выполненных задач можно вычислить селектором из массива задач. Это снижает риск получить два противоречащих друг другу значения.
Асинхронная логика и данные сервера
Редуктор не должен выполнять запрос к API: результат сети зависит от внешней среды и приходит не сразу. Для произвольной асинхронной последовательности стандартная настройка Redux Toolkit включает Redux Thunk, а createAsyncThunk помогает описать состояния выполнения, успеха и ошибки.
Для регулярного получения и кэширования серверных данных предусмотрен RTK Query. В первичной документации RTK Query в репозитории проекта запрос определяется как операция, которая получает данные с сервера и сохраняет результат в клиентском кэше; для изменения данных используются мутации.
Разделение зависит от назначения данных. Обычный срез подходит для клиентского рабочего состояния, thunk — для нестандартного процесса из нескольких шагов, а RTK Query — для загрузки, повторного получения и согласования серверных ресурсов. Дублировать один ответ одновременно в кэше RTK Query и обычном срезе без конкретной причины не стоит.
Когда Redux полезен, а когда избыточен
Redux особенно полезен, когда состояние используют многие экраны, изменения поступают из нескольких мест или правила обновления нужно отделить от интерфейса. Единая модель также упрощает обсуждение архитектуры в команде: у данных появляется понятный владелец и контролируемый путь изменения.
Для небольшой страницы, простой формы или изолированного виджета Redux может стать лишним уровнем. Передача свойств через один или два компонента сама по себе ещё не требует отдельного хранилища.
Контекст React решает другую задачу: он передаёт значение по дереву компонентов, но не задаёт модель событий, редукторов, промежуточного программного обеспечения и диагностики. Поэтому контекст не является ни обязательным этапом перед Redux, ни его полной заменой во всех сценариях.
- Оставляйте краткоживущие детали интерфейса рядом с компонентом.
- Переносите в Redux данные, которыми действительно пользуются разные функции приложения.
- Не храните вычисляемое значение отдельно, если его можно надёжно получить селектором.
- Выбирайте RTK Query для серверного кэша, а обычные срезы — для клиентского состояния.
Что важно запомнить
Redux — не фреймворк интерфейса и не база данных. Это самостоятельная библиотека управления состоянием с однонаправленным потоком изменений: действие поступает в хранилище, редукторы вычисляют новое состояние, а подписанные части приложения получают обновление.
Для нового проекта отправной точкой служат Redux Toolkit, configureStore и createSlice. В приложениях React к ним добавляются Provider, useSelector и useDispatch; createStore и connect могут встречаться в старом коде, но изучать их как основной современный способ уже не следует.
Читайте также:
Подпишитесь на рассылку
Получайте свежие новости Web3, AI и криптовалют прямо на вашу почту.