webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
Стейт-менеджмент · Урок 2 из 4

Redux Toolkit

Стор, действия, редьюсеры, createSlice с Immer и Redux в Next.

Обновлено

Что такое Redux

Redux — модель глобального состояния со строгими правилами:

  1. Всё глобальное состояние хранится в одном сторе.
  2. Состояние не меняют напрямую — отправляют (dispatch) действие: объект, описывающий, что произошло ({ type: 'cart/add', payload: item }).
  3. Редьюсер — чистая функция (state, action) => newState — вычисляет новое состояние.
UIdispatch(action)действие→reducer(state, action) => newStateновое состояние→storeселектор→UIперерисовывается

Плюс: любое изменение проходит через одно место → предсказуемо, тестируемо, а DevTools показывают каждое действие и умеют «перематывать» историю.

Redux Toolkit (RTK) — официальный и актуальный способ писать на Redux. «Классический» Redux (со switch, константами типов, connect) считается устаревшим.

Части Redux Toolkit

Часть Что делает
configureStore создаёт стор с DevTools и middleware в комплекте
createSlice описывает кусок состояния + его редьюсеры; генерирует действия автоматически
useSelector читает кусок стора (компонент перерисовывается, только когда этот кусок меняется)
useDispatch отправляет действия
createAsyncThunk асинхронная логика (сегодня редко — для данных есть RTK Query)
RTK Query запросы + кэш для серверного состояния — следующий урок

Слайс

// entities/cart/model/cart-slice.ts
import { createSlice, type PayloadAction } from '@reduxjs/toolkit'

type CartItem = { id: number; qty: number }

const cartSlice = createSlice({
  name: 'cart',
  initialState: [] as CartItem[],
  reducers: {
    added(state, action: PayloadAction<number>) {
      const item = state.find(i => i.id === action.payload)
      if (item) item.qty++                         // разрешённая «мутация» — см. Immer
      else state.push({ id: action.payload, qty: 1 })
    },
    removed(state, action: PayloadAction<number>) {
      return state.filter(i => i.id !== action.payload)
    },
  },
})

export const { added, removed } = cartSlice.actions
export const cartReducer = cartSlice.reducer

Immer: в createSlice можно писать код, который выглядит как изменение состояния (state.push, item.qty++). RTK использует библиотеку Immer, которая превращает эти «мутации» в новый иммутабельный объект. Правила из Ссылки и иммутабельность остаются в силе — просто синтаксис короче.

Стор и типизированные хуки

// shared/store/store.ts
export const makeStore = () => configureStore({ reducer: { cart: cartReducer } })

export type AppStore = ReturnType<typeof makeStore>
export type RootState = ReturnType<AppStore['getState']>
export type AppDispatch = AppStore['dispatch']

export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
'use client'
const count = useAppSelector(state => state.cart.length)
const dispatch = useAppDispatch()
<button onClick={() => dispatch(added(product.id))}>Добавить</button>

Redux с Next.js App Router

  • Стор создаётся на каждый запрос, а не как глобальная переменная модуля — иначе на сервере данные одного пользователя попадут к другому. Поэтому makeStore() — функция.
  • Его кладут в Client Component StoreProvider ('use client'), созданный один раз через useRef / useState.
  • Server Components не могут читать стор — они получают данные напрямую.

Когда Redux Toolkit

Да Нет
большое приложение, много команд, полезны строгие правила маленькое / среднее приложение
сложная логика с множеством переходов, нужны DevTools / time-travel совсем немного глобального UI-состояния
существующий проект на Redux состояние, которое на самом деле серверное

Коротко

  • Redux = один стор, действия, чистые редьюсеры; RTK — актуальный способ его писать.
  • createSlice + Immer = короткий код, иммутабельный результат.
  • В Next: стор на запрос, внутри Client Component; для серверных данных → RTK Query.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.