Redux Toolkit(简称 RTK)是 Redux 官方推荐的标准工具集,旨在解决传统 Redux 使用中“配置繁琐、样板代码多、容易出错”的痛点。它提供了简化的 API,让开发者可以更高效地编写可维护的状态管理逻辑,并且内置了 Immer、Redux Thunk、Redux DevTools 扩展等最佳实践。
为什么需要 RTK:传统 Redux 的痛点
传统 Redux 需要手动编写 action 类型常量、action creator 函数、reducer 中的 switch/case 逻辑,还要通过中间件(如 redux-thunk)处理异步,配置 Store 时也要组合多个 reducer、应用中间件。这些都导致代码量大且分散,新手容易犯错。
例如,一个简单的计数器在传统 Redux 中需要这样写:
// 1. 定义 action 类型
const INCREMENT = 'counter/increment';
const DECREMENT = 'counter/decrement';
// 2. 编写 action creator
function increment() { return { type: INCREMENT }; }
function decrement() { return { type: DECREMENT }; }
// 3. 编写 reducer
const initialState = { value: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case INCREMENT: return { value: state.value + 1 };
case DECREMENT: return { value: state.value - 1 };
default: return state;
}
}
// 4. 配置 store
const rootReducer = combineReducers({ counter: counterReducer });
const store = createStore(rootReducer, applyMiddleware(thunk));
而 RTK 通过 createSlice 和 configureStore 将上述步骤大幅简化,代码量减少 50% 以上,且类型推导更友好(配合 TypeScript)。
RTK 核心 API 与标准开发模式
1. configureStore:一行创建 Store
configureStore 替代了 createStore,自动组合多个 reducer、默认启用 Redux DevTools、内置 redux-thunk 中间件,还提供了更清晰的 middleware 配置。
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer,
// 其他 slices 的 reducer
},
});
export default store;
2. createSlice:消灭手写 action 和 reducer
createSlice 会自动生成 action creator 和对应的 reducer 逻辑,你只需要定义初始状态和同步的 reducer 函数。内部基于 Immer 库,允许你“直接修改”状态(实际上是生成不可变更新),代码更自然。
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) {
state.value += 1; // 看似直接修改,实际被 Immer 转为不可变操作
},
decrement(state) {
state.value -= 1;
},
incrementByAmount(state, action) {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
使用 createSlice 后,你无需再定义 action 类型常量,counterSlice.actions.increment() 返回的 action 对象会自动包含 type: 'counter/increment',payload 自动映射。
3. createAsyncThunk:处理异步请求
createAsyncThunk 简化了异步 action 的编写,自动生成 pending、fulfilled、rejected 三种 action,你可以在 slice 的 extraReducers 中处理这些状态。这样避免了过去用 thunk 时手动 dispatch 多个 action 的繁琐。
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';
// 创建异步 thunk
export const fetchUserById = createAsyncThunk(
'users/fetchById',
async (userId) => {
const response = await axios.get(`/api/users/${userId}`);
return response.data; // 作为 fulfilled action 的 payload
}
);
const usersSlice = createSlice({
name: 'users',
initialState: { entities: [], loading: 'idle', error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserById.pending, (state) => {
state.loading = 'loading';
})
.addCase(fetchUserById.fulfilled, (state, action) => {
state.loading = 'idle';
state.entities.push(action.payload);
})
.addCase(fetchUserById.rejected, (state, action) => {
state.loading = 'idle';
state.error = action.error.message;
});
},
});
createAsyncThunk 的第一个参数是 action 类型前缀,第二个是异步执行函数。它返回的 thunk 可以直接 dispatch,例如 dispatch(fetchUserById(123))。
4. RTK Query:一站式数据获取与缓存
RTK Query 是 Redux Toolkit 附加的数据获取和缓存方案,类似于 React Query 或 SWR,但深度集成 Redux 状态管理。它通过定义 API endpoint 来自动生成 React hooks,让你在组件中调用即可获得加载、错误、数据等状态,并且自动管理缓存、重复请求去重、乐观更新等。
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
endpoints: (builder) => ({
getUsers: builder.query({ query: () => '/users' }),
getUserById: builder.query({ query: (id) => `/users/${id}` }),
addUser: builder.mutation({
query: (newUser) => ({ url: '/users', method: 'POST', body: newUser }),
}),
}),
});
export const { useGetUsersQuery, useGetUserByIdQuery, useAddUserMutation } = apiSlice;
在组件中直接使用这些 hooks,RTK Query 会自动处理数据的加载与更新,并可与 Redux Store 共享状态。
项目中推荐的使用结构
典型的 RTK 项目结构(基于官方推荐模式):
src/
app/
store.js // 配置 store
features/
counter/
counterSlice.js // 状态切片
users/
usersSlice.js
usersAPI.js // 如果用 RTK Query
components/...
这种组织方式让每个功能模块的状态、reducer、异步逻辑都放在一起,便于维护。
React 组件中的使用
通过 react-redux 提供的 useSelector 读取状态,useDispatch 派发 action。
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(decrement())}>-</button>
<span>{count}</span>
<button onClick={() => dispatch(increment())}>+</button>
</div>
);
}
RTK 带来的实质变化
- 代码量锐减:不再需要手动编写 action 类型、creator 和冗长的 switch。
- 安全性提升:Immer 让不可变更新不出错,内置了序列化检查等开发期警告。
- 异步管理统一:
createAsyncThunk规范了异步处理流程,告别散落的 dispatch。 - 性能优化开箱即用:
configureStore默认启用 Redux DevTools 和开发环境检查。 - 类型推导优秀:配合 TypeScript,slice 自动推导 state 类型和 action 类型。
何时选用 RTK
当你的应用具有以下特征时,RTK 是一个理想选择:
- 全局状态较多且复杂(20+ 个全局状态变量)
- 需要严格的单向数据流和清晰的状态变更历史(可时间旅行调试)
- 需要丰富的中间件支持(日志、持久化、副作用管理)
- 团队熟悉 Redux 模式或需要可预测的状态管理架构
对于简单应用,轻量的 Zustand 或 Jotai 可能更合适,但在中大型企业与复杂项目中,RTK 提供的规范化和工具链能显著降低维护成本,是 Redux 官方认证的现代标准写法。