Redux Toolkit: Быстрый старт без боли. Полное руководство для React-разработчиков

Redux Toolkit: Быстрый старт без боли. Полное руководство для React-разработчиков

Если вы работаете с React и устали от шаблонного кода, сложной настройки и многословности классического Redux, то Redux Toolkit (RTK) — это то, что кардинально изменит ваш опыт работы с состоянием приложения. Этот официальный пакет не просто набор утилит, а продуманный стандарт, который делает Redux предсказуемым, лаконичным и, наконец, приятным в использовании. Давайте разберемся, как быстро и эффективно начать с ним работать.

Что такое Redux Toolkit и зачем он нужен?

Redux Toolkit — это официальный, рекомендованный подход к написанию логики Redux. Он был создан для решения ключевых проблем «ванильного» Redux: избыточности кода, сложности настройки store и необходимости использования множества дополнительных библиотек. RTK включает в себя утилиты, которые абстрагируют стандартные шаги, навязывая при этом лучшие практики.

Главная философия RTK — «opinionated». Он предлагает готовые решения для большинства типовых задач, что ускоряет разработку и снижает количество ошибок.

Быстрый старт: Установка и базовая настройка

Начнем с самого начала. Установка выполняется одной командой в вашем React-проекте:

1. Установка пакетов

Используйте npm или yarn для установки необходимых зависимостей:

npm install @reduxjs/toolkit react-redux

Или, если вы начинаете проект с нуля, можно использовать официальный шаблон:

npx create-react-app my-app --template redux

2. Создание store (хранилища)

В классическом Redux создание store было многоэтапным процессом. RTK сокращает его до нескольких строк. Создайте файл app/store.js:

import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
  reducer: {
    // Сюда позже добавим редюсеры
  },
});

configureStore автоматически подключает самые важные middleware (например, Redux Thunk для асинхронных операций) и включает поддержку Redux DevTools Extension. Вам больше не нужно делать это вручную!

3. Создание slice (среза состояния)

Это ключевая концепция RTK. Slice — это автономный модуль, который содержит логику для определенной части состояния. Он генерирует actions и reducer автоматически. Создадим slice для управления счетчиком (features/counter/counterSlice.js):

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  value: 0,
};

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1; // Можно мутировать состояние! (благодаря Immer)
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

// Экспортируем сгенерированные actions
 export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// Экспортируем редюсер
 export default counterSlice.reducer;

4. Добавление slice в store

Вернемся в store.js и добавим редюсер нашего счетчика:

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

5. Подключение store к React-приложению

В корневом файле приложения (например, index.js) оберните ваше приложение в Provider:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  
    
  
);

Использование состояния и actions в компонентах

Теперь вы можете легко получать данные и отправлять actions в любом компоненте с помощью хуков useSelector и useDispatch.

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './features/counter/counterSlice';

export function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    
{count}
); }

Асинхронная логика с createAsyncThunk

Одна из самых мощных возможностей RTK — createAsyncThunk. Он упрощает работу с асинхронными запросами (например, к API).

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchUserAPI } from './api';

// Создаем thunk
 export const fetchUserById = createAsyncThunk(
  'users/fetchByIdStatus',
  async (userId, thunkAPI) => {
    const response = await fetchUserAPI(userId);
    return response.data;
  }
);

const usersSlice = createSlice({
  name: 'users',
  initialState: { entities: [], loading: 'idle' },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserById.pending, (state) => {
        state.loading = 'loading';
      })
      .addCase(fetchUserById.fulfilled, (state, action) => {
        state.entities.push(action.payload);
        state.loading = 'idle';
      });
  },
});

Почему Redux Toolkit — это must-have?

  • Меньше шаблонного кода: Автогенерация actions и reducers.
  • Лучшие практики «из коробки»: Встроенная поддержка Immer (безопасная мутация состояния), Redux Thunk, DevTools.
  • Простота асинхронной логики: createAsyncThunk решает проблему обработки состояний загрузки, успеха и ошибки.
  • Официальный стандарт: Разработан и поддерживается командой Redux.

FAQ: Часто задаваемые вопросы

Нужно ли знать классический Redux перед изучением RTK?

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

Можно ли использовать RTK с TypeScript?

Да, Redux Toolkit отлично работает с TypeScript и предоставляет отличную типизацию «из коробки».

Чем RTK Query отличается от createAsyncThunk?

RTK Query — это отдельный мощный инструмент внутри RTK для управления кэшированием данных, полученных с сервера. createAsyncThunk — более низкоуровневая утилита для создания любых асинхронных actions. Для простых запросов часто достаточно createAsyncThunk, для сложных API-взаимодействий с кэшем лучше использовать RTK Query.

Обязательно ли использовать Immer и мутацию состояния?

Нет, вы можете писать иммутабельный код как в классическом Redux, но использование Immer (и мутаций) — это одна из ключевых фишек RTK, которая делает код чище и понятнее.