Redux Toolkit
Redux 官方推荐的标准化状态管理工具集,以"开箱即用"的方式提供高效、可预测的全局状态管理能力。
Redux Toolkit 是 Redux 官方的"有态度"工具集,整合 Redux、Immer、Reselect、Redux Thunk 等核心依赖。提供 createSlice、createAsyncThunk、RTK Query 等 API,v2.0 全面 TypeScript 重写,DevTools 时间旅行调试无可替代,仍是大型企业级应用核心选择。
Redux Toolkit
Redux 官方推荐的标准化状态管理工具集,以"开箱即用"的方式提供高效、可预测的全局状态管理能力,是当前 React 生态中成熟度最高的状态管理方案之一。
技术简介说明
Redux Toolkit(简称 RTK)是 Redux 团队官方推出的"有态度"(opinionated)工具集,旨在解决传统 Redux 开发中样板代码过多、配置复杂、缺少 TypeScript 支持等痛点。它将 Redux、Redux Thunk、Immer、Reselect、Redux DevTools Extension 等核心依赖整合为一个统一的包,提供了 createSlice、createAsyncThunk、configureStore、createEntityAdapter、RTK Query 等一系列经过最佳实践验证的 API,使开发者能够以更少的代码实现更健壮的状态管理逻辑。
RTK 2.0 于 2023 年底发布,是一次重要的里程碑更新,伴随着 Redux 5.0、React-Redux 9.0 和 Reselect 5.0 的同步升级。此版本引入了 combineSlices 实现运行时 reducer 懒加载、全新的 Listener Middleware 替代 Redux-Saga 的大部分场景、Slice 内嵌 Selector 定义、动态中间件注入、自动批处理增强器等关键新特性,同时在 TypeScript 类型安全、生产包体积和运行性能上都有显著提升。截至 2026 年中期,RTK 最新版为 v2.12.0,持续维护并新增了对 React 19、RTK Query 无限查询等能力的支持。
尽管 2025-2026 年间 Zustand、Jotai 等轻量级方案在新项目中快速崛起,Redux Toolkit 凭借无可替代的 DevTools 时间旅行调试、成熟的中件间生态、RTK Query 内置数据获取、以及大量企业级项目的存量基础,依然是大型复杂应用和长生命周期项目的核心选择之一。RTK 不再是"默认选择",但仍然是"最强工具箱"之一。
基本信息
| 项目 | 内容 |
|---|---|
| 官网 | https://redux-toolkit.js.org/ |
| GitHub | https://github.com/reduxjs/redux-toolkit |
| License | MIT |
| 最新版本 | v2.12.0(2026 年 5 月 15 日) |
| 创建者 / 主要维护者 | Mark Erikson(@markerikson),Redux 官方团队 |
| GitHub Stars | ~11,200(2026 年 7 月) |
| npm 周下载量 | ~20.6M+(2026 年 5 月) |
| 框架支持 | 框架无关(核心),React 绑定通过 react-redux |
| TypeScript | 原生支持,2.0 后完全基于 TypeScript 重写 |
| 首次发布 | 2019 年(Redux Toolkit v1.0) |
| Bundle Size | ~14kB(gzip,含 Redux + Immer + Reselect) |
快速上手
安装
# npm
npm install @reduxjs/toolkit react-redux
# pnpm
pnpm add @reduxjs/toolkit react-redux
# yarn
yarn add @reduxjs/toolkit react-redux注意:
react-redux是 Redux 的 React 绑定包,需单独安装。如果你还需要数据获取能力,无需额外安装包——RTK Query 已内置于@reduxjs/toolkit。
基础配置
// app/store.ts
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
import todosReducer from '../features/todos/todosSlice'
import apiReducer from '../services/api/apiSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
todos: todosReducer,
// RTK Query 自动生成的 reducer
[apiReducer.reducerPath]: apiReducer,
},
// RTK Query 自动生成的中间件
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(apiReducer.middleware),
// 可选:自定义 DevTools 配置
devTools: process.env.NODE_ENV !== 'production'
? { trace: true, traceLimit: 25 }
: false,
})
// 推导 RootState 和 AppDispatch 类型
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch// app/hooks.ts — 类型安全的 hooks
import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import { store } from './app/store'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
)最小示例
// features/counter/counterSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
interface CounterState {
value: number
status: 'idle' | 'loading' | 'failed'
}
const initialState: CounterState = {
value: 0,
status: 'idle',
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
// Immer 允许直接修改 state
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
},
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer// features/counter/Counter.tsx
import { useAppSelector, useAppDispatch } from '../../app/hooks'
import { increment, decrement, incrementByAmount } from './counterSlice'
export function Counter() {
const count = useAppSelector((state) => state.counter.value)
const dispatch = useAppDispatch()
return (
<div>
<h2>计数器: {count}</h2>
<button onClick={() => dispatch(decrement())}>减少</button>
<button onClick={() => dispatch(increment())}>增加</button>
<button onClick={() => dispatch(incrementByAmount(5))}>增加 5</button>
</div>
)
}// features/todos/todosSlice.ts — 异步操作示例
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
interface Todo {
id: number
title: string
completed: boolean
}
interface TodosState {
items: Todo[]
loading: boolean
error: string | null
}
// 创建异步 thunk
export const fetchTodos = createAsyncThunk(
'todos/fetchTodos',
async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos?_limit=10')
if (!response.ok) throw new Error('网络请求失败')
return response.json() as Promise<Todo[]>
}
)
const todosSlice = createSlice({
name: 'todos',
initialState: { items: [], loading: false, error: null } as TodosState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchTodos.pending, (state) => {
state.loading = true
state.error = null
})
.addCase(fetchTodos.fulfilled, (state, action: PayloadAction<Todo[]>) => {
state.loading = false
state.items = action.payload
})
.addCase(fetchTodos.rejected, (state, action) => {
state.loading = false
state.error = action.error.message ?? '未知错误'
})
},
})
export default todosSlice.reducer核心概念与架构
核心架构设计
Redux Toolkit 的架构建立在单向数据流(Unidirectional Data Flow)原则之上,通过分层设计将状态管理逻辑与视图层解耦:
┌──────────────────────────────────────────────────────────────┐
│ View 层(React 组件) │
│ useSelector() ← 读取 state dispatch() → 发送 action │
├──────────────────────────────────────────────────────────────┤
│ react-redux(绑定层) │
│ <Provider> 注入 store,useSelector / useDispatch hooks │
├──────────────────────────────────────────────────────────────┤
│ Redux Toolkit 工具层 │
│ createSlice │ createAsyncThunk │ RTK Query │ createEntityAdapter│
│ createListenerMiddleware │ combineSlices │ createDynamicMiddleware│
├──────────────────────────────────────────────────────────────┤
│ Redux Core(状态容器) │
│ Store │ Reducer │ Action │ Middleware Chain │
├──────────────────────────────────────────────────────────────┤
│ 内置依赖层 │
│ Immer(不可变更新)│ Reselect(记忆化)│ Redux Thunk(异步) │
│ Redux DevTools(调试)│ autoBatchEnhancer(批处理) │
└──────────────────────────────────────────────────────────────┘
核心概念
-
Store(存储):应用的全局状态树,由
configureStore创建。整个应用只有一个 Store,它是唯一的状态真相来源(Single Source of Truth)。 -
Slice(切片):由
createSlice定义,包含一块状态(state)、初始值、以及更新这块状态的 reducer 函数。每个 Slice 自动生成对应的 Action Creator。 -
Action(动作):描述"发生了什么"的普通对象,必须包含
type字段(字符串)。由 Slice 的 reducer 自动生成,开发者无需手动定义。 -
Reducer(归约器):纯函数,接收当前 state 和 action,返回新的 state。RTK 通过内置 Immer,允许在 reducer 中编写"可变"代码,Immer 会自动将其转换为不可变更新。
-
Thunk(异步逻辑):由
createAsyncThunk创建,用于封装异步操作(API 请求等),自动生成pending/fulfilled/rejected三个生命周期 action。 -
Middleware(中间件):位于 action 发出到 reducer 执行的管道中,用于日志、异步处理、错误上报等副作用。RTK 默认配置了 Thunk 中间件和 RTK Query 中间件。
-
Selector(选择器):从 Store 中提取特定数据的函数,配合 Reselect 实现记忆化,避免不必要的重渲染。
核心特性
1. createSlice — 简化的 Slice 定义
将 reducer 定义、初始状态和 action 创建合并为一个 API,内部使用 Immer 允许直接修改 state 的"写法",实际执行时自动转为不可变更新。支持 extraReducers 的 builder 回调语法处理异步 action。
const userSlice = createSlice({
name: 'user',
initialState: { name: '', email: '', status: 'idle' } as UserState,
reducers: {
logout: (state) => { state.name = ''; state.email = '' },
},
extraReducers: (builder) => {
builder
.addCase(loginUser.fulfilled, (state, action) => {
state.name = action.payload.name
state.email = action.payload.email
state.status = 'authenticated'
})
},
})2. createAsyncThunk — 异步逻辑标准化
封装异步操作为标准化的 pending / fulfilled / rejected 三阶段 action,自动处理 loading 状态和错误状态,消除了手写样板代码的需要。
export const fetchUserById = createAsyncThunk(
'users/fetchById',
async (userId: string, { rejectWithValue }) => {
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) throw new Error('用户不存在')
return await response.json()
} catch (err) {
return rejectWithValue(err.message)
}
}
)3. RTK Query — 内置数据获取与缓存
集成在 RTK 中的数据获取解决方案,提供自动缓存、缓存失效、轮询、乐观更新、标签式失效等能力,灵感来自 React Query 和 Apollo,但完全融入 Redux 数据流。
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
tagTypes: ['Pokemon'],
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
providesTags: (result, error, name) => [{ type: 'Pokemon', id: name }],
}),
updatePokemon: builder.mutation<Pokemon, Partial<Pokemon> & Pick<Pokemon, 'id'>>({
query: ({ id, ...patch }) => ({
url: `pokemon/${id}`,
method: 'PATCH',
body: patch,
}),
invalidatesTags: (result, error, { id }) => [{ type: 'Pokemon', id }],
}),
}),
})
export const { useGetPokemonByNameQuery, useUpdatePokemonMutation } = pokemonApi4. createEntityAdapter — 规范化数据管理
专为管理集合数据(CRUD 列表)设计,提供标准化的数据结构({ ids: [], entities: {} })和预置的增删改查操作,自动维护排序和去重。
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'
interface User { id: string; name: string; age: number }
const usersAdapter = createEntityAdapter<User>({
selectId: (user) => user.id,
sortComparer: (a, b) => a.name.localeCompare(b.name),
})
const usersSlice = createSlice({
name: 'users',
initialState: usersAdapter.getInitialState(),
reducers: {
userAdded: usersAdapter.addOne,
userUpdated: usersAdapter.updateOne,
userRemoved: usersAdapter.removeOne,
usersReceived: usersAdapter.setAll,
},
})
// 自动生成的选择器
const { selectAll: selectAllUsers, selectById: selectUserById } = usersAdapter.getSelectors<RootState>(state => state.users)5. combineSlices — 运行时 Reducer 懒加载
RTK 2.0 引入的新 API,允许在 Store 创建后动态注入 slice reducer,支持代码拆分(Code Splitting)和按路由懒加载 reducer。
import { combineSlices } from '@reduxjs/toolkit'
// 支持动态注入的 rootReducer
const rootReducer = combineSlices({
auth: authSlice,
ui: uiSlice,
})
// 在路由组件中按需注入
function AdminPage() {
const adminReducer = useSelector(
() => rootReducer.inject({ reducerPath: 'admin', reducer: adminSlice })
)
// ...
}6. createListenerMiddleware — 现代副作用管理
RTK 2.0 引入的中间件,用于处理复杂的副作用逻辑(如 action 监听、条件触发、取消等),目标是替代 Redux-Saga 的大部分使用场景,API 更简洁且完全类型安全。
import { createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit'
const listenerMiddleware = createListenerMiddleware()
// 监听特定 action 并执行副作用
listenerMiddleware.startListening({
actionCreator: userLoggedIn,
effect: async (action, listenerApi) => {
// 监听后续的 action
const result = await listenerApi.condition(
(action) => isAnyOf(orderPlaced, orderFailed)(action),
30000 // 30 秒超时
)
if (result) {
// 处理结果
}
},
})7. createDynamicMiddleware — 运行时中间件注入
允许在 Store 创建后再添加新的中间件,用于插件系统或按需加载的功能模块。
8. 自动批处理增强器
configureStore 默认包含 autoBatchEnhancer,自动延迟低优先级 action 的订阅通知,减少不必要的重渲染,配合 React 18 的并发特性效果更佳。
9. 一流的 TypeScript 支持
RTK 2.0 的 Redux Core 完全由 TypeScript 重写,提供精确的类型推导:UnknownAction 替代 AnyAction、createSlice 的 action/reducer 类型自动推导、createEntityAdapter 的 Id 泛型等。
10. 内置 Redux DevTools 集成
开箱即用的时间旅行调试、action 回放、state diff 查看、action 搜索等能力,是所有状态管理库中 DevTools 生态最成熟的方案。
生态图
Redux Toolkit 生态
├── @reduxjs/toolkit —— 核心工具集(含 RTK Query)
├── redux —— 状态容器核心(v5.0+)
├── react-redux —— React 绑定层(v9.0+)
├── reselect —— 记忆化选择器(v5.0+)
├── redux-thunk —— 异步中间件(内置)
├── immer —— 不可变数据更新(内置,v10.0+)
│
├── 官方 DevTools
│ ├── @redux-devtools/extension —— 浏览器扩展
│ └── @redux-devtools/app —— 独立应用
│
├── 社区中间件与增强器
│ ├── redux-logger —— 日志中间件
│ ├── redux-persist —— 状态持久化(localStorage / AsyncStorage)
│ ├── redux-saga —— Generator 副作用管理(逐步被 Listener Middleware 替代)
│ ├── redux-observable —— RxJS 副作用管理
│ └── redux-first-history —— 路由历史管理
│
├── 数据获取扩展
│ ├── RTK Query(内置) —— 基于 REST 的数据获取
│ └── @rtk-query/graphql-request-base-query —— GraphQL 适配器
│
└── 工具链
├── @reduxjs/toolkit-query —— RTK Query 核心
├── reselect-tools —— Selector 调试工具
└── redux-starter-kit —— 旧名称(已废弃)
适用场景
1. 大型企业级应用
需要严格的状态管理规范、清晰的数据流向、可预测的行为。RTK 的单向数据流和 DevTools 时间旅行调试是团队协作和长期维护的关键保障。
2. 复杂客户端状态逻辑
涉及多模块联动的状态管理(如购物车 + 订单 + 支付 + 库存联动),RTK 的 slice 划分、middleware 链和 extraReducers 能优雅地处理跨 slice 的状态交互。
3. 需要时间旅行调试的项目
金融系统、医疗应用等对数据变更有严格审计要求的场景,Redux DevTools 的 action 回放、state diff 查看和时间旅行是无可替代的能力。
4. 服务端状态管理(RTK Query)
项目需要统一的 API 数据获取方案,且不想额外引入 TanStack Query / SWR。RTK Query 提供缓存、轮询、标签式失效、乐观更新等完整能力。
5. 已有 Redux 历史的项目迁移
大量 2015-2022 年间创建的 React 项目使用旧版 Redux,RTK 2.0 提供了完整的迁移路径,使旧项目可以逐步采用现代化 API。
6. 跨框架共享状态逻辑
RTK 核心是框架无关的,可以在 React、Vue、Angular 甚至非 UI 场景(如 Web Worker、Node.js)中共享同一套状态管理逻辑,只有 UI 绑定层需要适配。
7. 微前端 / 模块化应用
通过 combineSlices 的懒加载能力,各微前端模块可以独立注册自己的 slice reducer,实现状态层的按需加载和代码拆分。
开发与工程化
TypeScript 支持
RTK 2.0 全面基于 TypeScript 重写,提供精确的类型推导:
// 类型安全的 action payload
interface User {
id: string
name: string
role: 'admin' | 'user'
}
const userSlice = createSlice({
name: 'user',
initialState: { data: null as User | null, loading: false },
reducers: {
// PayloadAction<T> 自动推导 payload 类型
setUser: (state, action: PayloadAction<User>) => {
state.data = action.payload // action.payload 类型为 User
},
setRole: (state, action: PayloadAction<'admin' | 'user'>) => {
if (state.data) state.data.role = action.payload
},
},
})
// 类型安全的 selector
const selectUser = (state: RootState) => state.user.data
const selectUserRole = (state: RootState) => state.user.data?.roleESLint 集成
推荐使用 eslint-plugin-redux-toolkit 和 eslint-plugin-react-redux:
pnpm add -D eslint-plugin-react-redux{
"plugins": ["react-redux"],
"rules": {
"react-redux/use-selector-in-extra-callbacks": "warn",
"react-redux/map-state-props": "warn"
}
}测试策略
// features/counter/counterSlice.test.ts
import counterReducer, { increment, decrement, incrementByAmount } from './counterSlice'
describe('counterSlice', () => {
const initialState: CounterState = { value: 0, status: 'idle' }
it('应处理初始状态', () => {
expect(counterReducer(undefined, { type: 'unknown' })).toEqual(initialState)
})
it('应处理 increment', () => {
const actual = counterReducer(initialState, increment())
expect(actual.value).toBe(1)
})
it('应处理 decrement', () => {
const actual = counterReducer({ value: 3, status: 'idle' }, decrement())
expect(actual.value).toBe(2)
})
it('应处理 incrementByAmount', () => {
const actual = counterReducer(initialState, incrementByAmount(5))
expect(actual.value).toBe(5)
})
})// 异步 thunk 测试
import { fetchTodos } from './todosSlice'
import { store } from '../../app/store'
test('fetchTodos 应更新 todos 列表', async () => {
await store.dispatch(fetchTodos())
const state = store.getState()
expect(state.todos.loading).toBe(false)
expect(state.todos.items.length).toBeGreaterThan(0)
})生产环境配置建议
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => {
const middleware = getDefaultMiddleware({
// 生产环境关闭序列化检查以提升性能
serializableCheck: process.env.NODE_ENV !== 'production',
// 保留 thunk 中间件
thunk: true,
})
return middleware.concat(api.middleware)
},
devTools: process.env.NODE_ENV !== 'production'
? {
name: 'My App',
trace: true,
traceLimit: 25,
}
: false,
// 自动批处理,减少低优先级更新
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers({ autoBatch: { type: 'tick' } }),
})性能与安全
性能优化
- 记忆化 Selector:使用 Reselect 的
createSelector避免重复计算派生数据:
import { createSelector } from 'reselect'
const selectUsers = (state: RootState) => state.users.items
const selectFilter = (state: RootState) => state.ui.filter
const selectFilteredUsers = createSelector(
[selectUsers, selectFilter],
(users, filter) => users.filter(user => user.status === filter)
)- 选择性订阅:
useSelector配合浅比较,只订阅需要的 state 片段:
// 推荐:只订阅需要的值,避免不必要的重渲染
const userName = useAppSelector((state) => state.user.data?.name)
// 或使用 shallowEqual 防止对象引用变化导致的重渲染
import { shallowEqual } from 'react-redux'
const user = useAppSelector((state) => state.user, shallowEqual)-
自动批处理:
autoBatchEnhancer(RTK 2.0 默认启用)自动延迟低优先级 action 的通知,减少渲染次数。 -
RTK Query 缓存共享:相同查询参数的多个组件共享同一份缓存数据,避免重复请求和状态存储。
-
Immer 10 性能提升:RTK 2.0 升级至 Immer 10,不可变更新的性能和包体积均有显著改善。
安全考量
-
Action 类型安全:RTK 2.0 强制要求
action.type为字符串,防止原型污染攻击。 -
序列化检查:开发模式下
serializableCheck中间件会检测 state 和 action 中的不可序列化值(如函数、undefined、Symbol),防止 Redux DevTools 和状态持久化出现问题。 -
敏感数据隔离:避免将 token、密码等敏感信息直接存入 Redux state,防止通过 DevTools 泄露。
-
状态持久化加密:使用
redux-persist时应配合redux-persist-transform-encrypt对存储数据进行加密。 -
XSS 防护:渲染来自 state 的用户输入数据时,必须做 HTML 转义,避免存储型 XSS。
-
中间件安全:自定义中间件需仔细处理异常,防止未捕获的错误导致整个中间件链中断。
技术对比
Redux Toolkit vs Zustand vs Jotai vs MobX vs Recoil vs Valtio
| 特性 | Redux Toolkit | Zustand | Jotai | MobX | Recoil | Valtio |
|---|---|---|---|---|---|---|
| 设计理念 | 单向数据流,不可变 | 单一 store,Hook 化 | 原子化,自底向上 | 响应式,可变对象 | 原子化,图结构 | Proxy 代理,可变 |
| Bundle Size | ~14kB(gzip) | ~3kB(gzip) | ~4kB(gzip) | ~16kB(gzip) | ~14kB(gzip) | ~3kB(gzip) |
| 学习曲线 | 中-高 | 低 | 低-中 | 中-高 | 中 | 低 |
| TypeScript 支持 | ⭐ 原生优秀 | ⭐ 良好 | ⭐ 良好 | ⭐ 良好 | 基础 | ⭐ 良好 |
| Boilerplate | 较多(但 RTK 大幅减少) | 极少 | 少 | 中等 | 少 | 极少 |
| DevTools | ⭐⭐⭐ 最强(时间旅行) | ⭐⭐ 通过中间件接入 | ⭐ React DevTools | ⭐⭐ MobX DevTools | ⭐ 基础 | ⭐ DevTools 扩展 |
| 数据获取 | ⭐ RTK Query 内置 | 需配合 TanStack Query | 需配合 React Query | 需自行集成 | 需配合 React Query | 需配合 SWR / React Query |
| 中间件生态 | ⭐⭐⭐ 最丰富 | ⭐⭐ 基础 | ⭐ 有限但增长中 | ⭐⭐ 成熟 | ⭐ 有限 | ⭐ 基础 |
| 不可变更新 | ⭐ Immer 自动处理 | 手动(可选 Immer) | 不适用 | 直接可变 | 手动 | 直接可变(Proxy) |
| 性能优化 | 需手动 memoize | 内置 shallow compare | ⭐ 原子级精细 | ⭐ 自动追踪依赖 | ⭐ 精细订阅 | ⭐ Proxy 自动追踪 |
| 服务端状态 | ⭐ RTK Query | 需配合外部库 | 需配合外部库 | 需自行集成 | 需配合外部库 | 需配合外部库 |
| 框架支持 | 框架无关(React 为主) | React / Vue / 框架无关 | React 为主 | React / Vue / 框架无关 | 仅 React | React 为主 |
| 社区活跃度(2026) | 高(维护模式) | ⭐ 极高(新项目首选) | 高 | 中 | 低(Meta 已停止维护) | 中 |
| npm 周下载量 | ~20.6M | ~5.8M | ~2.2M | ~1.5M | ~0.8M | ~0.7M |
| React 19 支持 | ⭐ v2.5.0+ | ⭐ | ⭐ | ⭐ | 不确定 | ⭐ |
选型建议
- 选 Redux Toolkit:大型企业应用、需要 DevTools 时间旅行、已有 Redux 历史、团队需要严格的状态管理规范、需要内置数据获取(RTK Query)
- 选 Zustand:新项目首选、追求简洁 API 和最小 bundle、小到中型项目、不需要复杂 middleware
- 选 Jotai:复杂的派生状态、原子化精细控制、Suspense 深度集成、表单构建器类应用
- 选 MobX:面向对象风格、复杂领域模型、需要自动依赖追踪、Vue/React 混合项目
- 不推荐 Recoil(2026):Meta 已基本停止维护,社区活跃度下降,新项目不建议选择
- 选 Valtio:极简偏好、函数式组件、不喜欢 Immer、需要最小化状态管理代码
最佳实践
1. Slice 设计原则
// 推荐:每个功能域一个 slice,保持职责单一
// features/auth/authSlice.ts
const authSlice = createSlice({
name: 'auth',
initialState: { user: null, token: null, status: 'idle' },
reducers: { /* 同步操作 */ },
extraReducers: (builder) => { /* 异步操作 */ },
})
// 避免:将所有逻辑塞进一个巨型 slice
// ❌ features/globalSlice.ts — 数百个 reducer,难以维护2. Selector 与记忆化
// 推荐:使用 createSelector 避免重复计算
const selectFilteredTodos = createSelector(
[(state: RootState) => state.todos.items, (state: RootState) => state.filter.value],
(todos, filter) => todos.filter(todo =>
filter === 'all' ? true : todo.completed === (filter === 'completed')
)
)
// 在组件中使用
const filteredTodos = useAppSelector(selectFilteredTodos)3. RTK Query 标签失效
// 推荐:使用 tagTypes 管理缓存失效关系
const api = createApi({
// ...
tagTypes: ['User', 'Post'],
endpoints: (builder) => ({
getUsers: builder.query({
query: () => '/users',
providesTags: (result) =>
result ? result.map(({ id }) => ({ type: 'User', id })) : ['User'],
}),
updateUser: builder.mutation({
query: (user) => ({ url: `/users/${user.id}`, method: 'PUT', body: user }),
// 精确失效:只失效被更新的用户
invalidatesTags: (result, error, { id }) => [{ type: 'User', id }],
}),
}),
})4. 状态分层
// 推荐:按职责分离状态层
// - RTK / Zustand:客户端全局状态(用户会话、权限、UI 配置)
// - RTK Query / TanStack Query:服务端状态(API 数据缓存)
// - useState / useReducer:局部组件状态(表单、弹窗开关)
// - URL state(React Router):路由参数、筛选条件、分页5. 避免在 Selector 中创建新对象
// ❌ 避免:每次调用都创建新数组引用
const selectCompleted = (state: RootState) =>
state.todos.items.filter(t => t.completed)
// ✅ 推荐:使用 createSelector 记忆化结果
const selectCompleted = createSelector(
[(state: RootState) => state.todos.items],
(items) => items.filter(t => t.completed)
)技术局限与边界
1. 包体积较大
RTK 的 gzip 后体积约 14kB(含 Redux + Immer + Reselect + Thunk),相比 Zustand 的 3kB 和 Valtio 的 3kB 明显更大。在对 bundle size 敏感的场景(如移动端 H5、嵌入式组件),轻量级方案可能更合适。
2. 学习曲线较陡
尽管 RTK 大幅简化了 Redux,但开发者仍需理解 Action、Reducer、Store、Middleware、Thunk、Selector、Immer 等概念,对于初学者或小团队来说入门成本高于 Zustand 等方案。
3. 不适合纯服务端状态
RTK Query 虽然内置了数据获取能力,但相比 TanStack Query 这样的专注方案,在缓存策略灵活性、框架无关性和 API 简洁性上仍有差距。2026 年的趋势是 RTK 管客户端状态,TanStack Query 管服务端状态。
4. 性能优化需手动干预
虽然 autoBatchEnhancer 和 Reselect 帮助减轻了一些性能问题,但复杂应用中仍需要开发者主动使用 shallowEqual、记忆化 Selector、选择性订阅等手段来避免不必要的重渲染。
5. Redux-Saga 迁移成本
虽然 createListenerMiddleware 可以替代 Redux-Saga 的大部分功能,但已有 Redux-Saga 代码的项目迁移成本较高,API 模式差异较大。
6. 新项目不再是默认选择
2026 年的 React 社区共识是:新项目优先考虑 Zustand(客户端状态)+ TanStack Query(服务端状态),Redux Toolkit 更适合已有 Redux 基础或确实需要其完整能力的项目。
7. React Server Components 的适配
在 Next.js App Router 的 Server Components 架构下,Redux 的 Store 只能在 Client Components 中使用,<Provider> 必须在 Client 边界内包裹。对于大量服务端渲染的应用,Redux 的价值有所降低。
学习资源
官方资源
- Redux Toolkit 官方文档 — 最权威的参考
- RTK 2.0 迁移指南 — 从 1.x 迁移的详细指南
- Redux 官方文档 — Redux 核心概念
- RTK Query 教程 — 数据获取入门
视频教程
- What's New in Redux Toolkit 2.0 — Mark Erikson — 核心维护者亲自讲解
- Redux Toolkit Full Course 2026 — 2026 年最新完整教程
- Mastering Redux Toolkit 2.0 — 进阶指南
文章与博客
- Redux Toolkit Best Practices in 2026 — 2026 年最佳实践
- React in 2026: Do You Still Need Redux? — 2026 年 Redux 的定位分析
- Modern Redux with Redux Toolkit & RTK Query in 2026 — 现代 Redux 开发指南
- Advanced Redux Toolkit Patterns — 高级模式
中文资源
- Redux Toolkit 中文文档 — 官方中文文档
- RTK 2.0 迁移指南(中文) — 中文版迁移指南
- Redux Toolkit 核心 API 深度解析 — 四大核心 API 详解
GitHub 讨论
- v2.0.0 Release Discussion #3945 — 2.0 发布讨论
- RTK Query Infinite Query Support — v2.6.0 无限查询特性
2026 年现状
版本状态
截至 2026 年 7 月:
| 版本 | 发布日期 | 关键特性 |
|---|---|---|
| v2.0.0 | 2023 年底 | Redux 5 + combineSlices + Listener Middleware + 全面 TS 重写 |
| v2.5.0 | 2024 年 12 月 | React 19 支持 |
| v2.6.0 | 2025 年 2 月 | RTK Query 无限查询支持 |
| v2.12.0 | 2026 年 5 月 | 当前最新,TanStack Intent 集成、类型导出优化 |
关键动态
-
不再是默认选择:2026 年 React 新项目的状态管理选型中,Zustand 凭借极简 API 和 3KB 体积成为社区首选,RTK 退居"大型项目专属方案"定位。
-
维护模式稳定演进:RTK 进入稳定维护阶段,v2.x 系列持续发布修复和小特性,暂无 v3.0 的破坏性变更计划。
-
RTK Query 持续增强:v2.6.0 新增了无限查询(Infinite Query)支持,使 RTK Query 在分页场景的能力更加完善。
-
React 19 完全支持:自 v2.5.0 起,RTK 的 peer dependency 已更新支持 React 19,确保与最新 React 版本兼容。
-
Listener Middleware 逐步替代 Saga:
createListenerMiddleware在 2.0 后持续完善,越来越多的项目用它替代 Redux-Saga,简化副作用管理。 -
存量市场依然庞大:尽管新项目选择减少,但 RTK 的 npm 周下载量仍高达 20.6M,大量企业级项目仍在积极使用和招聘相关技能。
未来展望
- v3.0 可能性:社区已有讨论,但目前无正式路线图。预计若有 v3.0,将聚焦于进一步精简 API 和与 Signals 标准的互操作。
- 与 Signals 的关系:Redux 团队正在关注 TC39 Signals 提案,未来可能提供与 Signals 的互操作层。
- AI 应用场景:RTK 在管理 AI 应用的复杂状态(如多轮对话上下文、流式响应)方面仍有独特价值。
- 持续维护:Mark Erikson 和 Redux 团队承诺持续维护 RTK,确保其与 React 生态的最新发展保持同步。
本文档基于 2026 年 7 月调研数据编写,信息可能随版本更新而变化。建议参考 官方文档 获取最新信息。