Если вы работаете с 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, которая делает код чище и понятнее.