Redux 全局状态管理实战指南:核心 API、Redux Toolkit 与项目接入
2026/9/18 18:14:42 网站建设 项目流程

Redux 全局状态管理实战指南:核心 API、Redux Toolkit 与项目接入

【免费下载链接】reduxA JS library for predictable global state management项目地址: https://gitcode.com/gh_mirrors/re/redux

Redux 是一个用于"可预测且可维护的全局状态管理"的 JavaScript 库。本文以当前仓库(redux 5.0.1)的 README 与src/源码为准,系统讲解 Redux 的核心思想、安装接入方式、Redux Toolkit 推荐用法与传统手写 Redux 的差异,并结合仓库内示例与源码实现,帮助读者快速上手并理解底层原理。

Redux 是什么:一个可预测的全局状态容器

Redux 的定位是可预测(predictable)且可维护(maintainable)的全局状态管理库(仓库 package.json 中的官方描述为 "A JS library for predictable and maintainable global state management")。

它帮助你写出这样的应用:

  • 行为一致:无论运行环境如何,状态变化路径都是确定的;
  • 跨环境运行:同时支持客户端(浏览器)、服务端(Node/SSR)与原生环境(React Native 等);
  • 易于测试:状态更新逻辑是纯函数,可独立测试;
  • 开发者体验好:配合 Redux DevTools 可实现"实时代码编辑 + 时间旅行调试器",把每次状态变更都回放出来。

Redux 可以与 React 配合使用,也可以与任何其他视图库配合使用。Redux 核心库本身非常小(README 称其含依赖仅约 2kB),并拥有庞大的插件生态。

重要定位:Redux Toolkit 明确指出:今天编写任何新的 Redux 代码都应该使用 Redux Toolkit,而redux核心包仅建议用于学习底层原理。

安装与项目初始化

方式一:创建 React + Redux 应用(官方推荐)

官方推荐通过模板起步,两种主流构建工具各有对应模板:

# Vite + Redux Toolkit + TypeScript 模板 # (使用 degit 工具克隆并解压模板) npx degit reduxjs/redux-templates/packages/vite-template-redux my-app # Next.js 使用 with-redux 模板 npx create-next-app --example with-redux my-app

这两个模板都已针对对应构建工具配置好 Redux Toolkit 与 React-Redux,并附带一个演示多种 Redux Toolkit 特性的小示例应用。

对于 React Native 场景,官方目前没有官方模板,但推荐使用社区模板(标准 React Native 与 Expo 各一);同时基础依赖安装命令为:

npm install @reduxjs/toolkit react-redux

方式二:仅安装 Redux 核心库

如果只需要 Redux 核心库本身:

npm install redux

方式三:手动初始化(结合本仓库)

本仓库正是redux核心库源码(版本 5.0.1,见 package.json)。使用现代模块打包器或 Node 应用时,可从redux包导入核心 API。仓库根目录提供了可直接运行验证的示例应用,例如:

  • examples/counter —— Redux Toolkit + React 计数器;
  • examples/counter-ts —— TypeScript 版本;
  • examples/counter-vanilla —— 不依赖框架的纯 Redux 示例;
  • examples/async、examples/real-world、examples/shopping-cart、examples/todomvc、examples/todos、examples/todos-with-undo、examples/tree-view、examples/universal 等,覆盖异步逻辑、服务端渲染、撤销历史等典型场景。

关于各平台安装细节,可参见 docs/introduction/Installation.md 与 docs/introduction/GettingStarted.md。

核心 API 一览:Redux 核心做了什么

Redux 核心是一个非常小且刻意不预设观点的库(详见 docs/introduction/why-rtk-is-redux-today.md),只提供少量 API 原语。仓库入口 src/index.ts 导出的内容包括:

API作用源码位置
createStore创建 Redux store(已标记 deprecated,推荐改用configureStoresrc/createStore.ts
legacy_createStore不带弃用警告的createStore别名src/createStore.ts
combineReducers把多个 slice reducer 合并成一个根 reducersrc/combineReducers.ts
applyMiddleware把多个 middleware 组合成 store enhancersrc/applyMiddleware.ts
compose从右到左组合多个单参数函数src/compose.ts
bindActionCreators把 action creator 包装成可直接调用的 dispatch 函数src/bindActionCreators.ts
isAction/isPlainObject类型判断工具函数src/utils/isAction.ts、src/utils/isPlainObject.ts
__DO_NOT_USE__ActionTypesRedux 内部使用的私有 action 类型常量src/utils/actionTypes.ts

入口同时导出了完整的 TypeScript 类型(StoreDispatchReducerMiddlewareAction等),见 src/index.ts。

Store 的五个核心行为(源码级)

从 src/createStore.ts 的实现可以确认 store 暴露的能力:

  1. getState():读取当前状态树。注意 reducer 执行期间调用会抛错(src/createStore.ts)。
  2. dispatch(action):触发状态变化的唯一途径。dispatch 会做严格校验——action 必须是普通对象、type不能为undefinedtype必须是字符串、reducer 内不允许再 dispatch(src/createStore.ts)。
  3. subscribe(listener):注册变更监听,返回取消订阅函数;监听器列表在每次 dispatch 前做快照,避免派发中途订阅/退订引发的问题(src/createStore.ts)。
  4. replaceReducer(nextReducer):热替换 reducer,常用于代码分割动态加载 reducer 或热更新(src/createStore.ts)。
  5. observable():提供对 observable/reactive 库的互操作点(src/createStore.ts)。

值得注意的实现细节:store 创建时会自动 dispatch 一个INIT动作,让每个 reducer 返回自己的初始状态,从而填充整棵初始状态树(src/createStore.ts)。createStore的类型与 JSDoc 注释还特别强调:应只存在单一 store,可用combineReducers组合 reducer,preloadedState可用于服务端渲染水合或恢复序列化会话(src/createStore.ts)。

combineReducers的合并逻辑同样值得关注:它会逐个调用子 reducer 并用hasChanged比较新旧引用,只有当某个 slice 的引用发生变化时才返回新状态对象,否则复用原状态(src/combineReducers.ts);同时会在开发模式下校验"初始状态不能为 undefined"以及"遇到未知 action 必须返回当前状态"(src/combineReducers.ts)。

基础示例:用 Redux Toolkit 编写 Redux 逻辑(推荐方式)

README 明确指出:应用的全部全局状态存储在一个单一 store 内的对象树中;改变状态树的唯一方式就是创建描述"发生了什么"的 action 对象并 dispatch 给 store;而状态如何响应 action 更新,则由纯 reducer 函数(根据旧状态和 action 计算新状态)决定。

Redux Toolkit 简化了编写 Redux 逻辑与配置 store 的过程。README 中的基础示例(完整代码):

import { createSlice, configureStore } from '@reduxjs/toolkit' const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { incremented: state => { // Redux Toolkit 允许我们在 reducer 中编写"可变"逻辑。它并不会真正修改 // state,因为底层使用了 Immer 库:Immer 检测对 "draft state" 的修改, // 并基于这些修改产出一个全新的不可变状态 state.value += 1 }, decremented: state => { state.value -= 1 } } }) export const { incremented, decremented } = counterSlice.actions const store = configureStore({ reducer: counterSlice.reducer }) // 仍然可以订阅 store store.subscribe(() => console.log(store.getState())) // 仍然向 dispatch 传递 action 对象,只不过这些对象由 Toolkit 帮我们创建 store.dispatch(incremented()) // {value: 1} store.dispatch(incremented()) // {value: 2} store.dispatch(decremented()) // {value: 1}

这个示例的关键点:

  • createSlice同时生成了 reducer 与 action creator,counterSlice.actions导出的incremented/decremented就是可以直接调用产生 action 的函数;
  • reducer 内使用"可变"写法(state.value += 1),但底层由 Immer 保证不可变性;
  • configureStore一步完成 store 配置(自动combineReducers、自动加redux-thunk、开发模式捕获意外突变、自动接入 Redux DevTools,见 docs/introduction/why-rtk-is-redux-today.md);
  • 订阅、dispatch、getState 这些核心行为与传统 Redux 完全一致,只是代码更短、更易读。

仓库中的 examples/counter/src/features/counter/counterSlice.js 与 examples/counter/src/app/store.js 是上述模式在真实 CRA 工程中的完整落地;TypeScript 版本见 examples/counter-ts/src/features/counter/counterSlice.ts 与 examples/counter-ts/src/app/store.ts。

对比:传统手写 Redux(legacy 写法)

为了理解 Redux Toolkit 解决了什么,需要看看传统手写写法(README 与 docs/introduction/GettingStarted.md 均给出了对照):

import { createStore } from 'redux' /** * 这是 reducer —— 一个接收当前 state 和描述"发生了什么"的 action 对象、 * 返回新 state 的函数。reducer 的函数签名是:(state, action) => newState * * Redux 的 state 应该只包含纯 JS 对象、数组和原始类型。 * 根 state 通常是一个对象。重要:不能修改 state 对象, * 状态变化时必须返回一个新对象。 * * reducer 里可以使用任何条件逻辑。本示例用 switch, * 但这并非强制要求。 */ function counterReducer(state = { value: 0 }, action) { switch (action.type) { case 'counter/incremented': return { value: state.value + 1 } case 'counter/decremented': return { value: state.value - 1 } default: return state } } // 创建持有应用状态的 Redux store。 // 它的 API 是 { subscribe, dispatch, getState }。 let store = createStore(counterReducer) // 可以用 subscribe() 在状态变化时更新 UI。 // 通常你会用视图绑定库(如 React Redux)而不是直接调 subscribe()。 store.subscribe(() => console.log(store.getState())) // 改变内部状态的唯一方式是 dispatch 一个 action。 // action 可以被序列化、记录或存储,之后还能重放。 store.dispatch({ type: 'counter/incremented' }) // {value: 1} store.dispatch({ type: 'counter/incremented' }) // {value: 2} store.dispatch({ type: 'counter/decremented' }) // {value: 1}

两种写法的对比结论(README 原话):Redux Toolkit 允许我们写出更短、更易读的逻辑,同时仍然遵循原始 Redux 核心的行为与数据流。传统写法中不可变更新需要大量手写对象展开和数组操作,极易误改 state(一直是 Redux bug 的头号原因),还常把单个功能的代码拆到多个文件;而 RTK 的createSlice+configureStore把这一切压缩到一个文件里。

关于两种方式的取舍与迁移路径,可进一步阅读:

  • docs/tutorials/fundamentals/part-8-modern-redux.md —— 展示如何把底层手写示例改写成现代 Redux Toolkit 等价物;
  • docs/usage/migrating-to-modern-redux.mdx —— 覆盖各类 legacy Redux 逻辑的迁移方案;
  • docs/introduction/why-rtk-is-redux-today.md —— 官方对"为何今天用 RTK 写 Redux"的完整论述。

深入学习路线:官方文档与教程

README 列出的文档体系在本仓库 docs/ 目录中有完整镜像,官方文档站点为 redux.js.org:

  • Introduction(入门):核心概念、生态、示例、安装、学习资源;
  • Tutorials(教程):
    • Redux Essentials 教程:docs/tutorials/essentials/part-1-overview-concepts.md —— "自顶向下"教程,教"如何用正确的方式使用 Redux",基于最新推荐 API 与最佳实践,官方建议从这里开始
    • Redux Fundamentals 教程:docs/tutorials/fundamentals/part-1-overview.md —— "自底向上"教程,从第一性原理讲解"Redux 如何工作",不借助任何抽象,并解释标准 Redux 用法模式为何存在;
  • Usage Guides(使用指南):涵盖派生数据与 selector、测试、reducer 逻辑结构、减少样板代码等主题;
  • FAQ(常见问题):回答大量关于如何使用 Redux 的常见问题,其中 docs/faq/General.md 详细讨论了"何时该用 Redux";
  • API Reference(API 参考):包含 createStore、applyMiddleware、combineReducers、compose、bindActionCreators 等完整 API 文档;
  • Style Guide(风格指南):官方推荐的最佳实践与建议。

Redux Toolkit 的文档(redux-toolkit.js.org)覆盖 RTK 全部 API 的参考与使用指南,包括configureStorecreateSlicecreateAsyncThunkcreateEntityAdaptercreateSelectorcreateListenerMiddleware以及可选的数据获取方案RTK Query@reduxjs/toolkit/query入口)。

动手验证:在仓库内运行与测试

本仓库可直接验证核心 API 行为:

  • 单元测试:核心行为均有 Vitest 测试覆盖,例如 test/createStore.spec.ts、test/combineReducers.spec.ts、test/applyMiddleware.spec.ts、test/compose.spec.ts、test/bindActionCreators.spec.ts;
  • 类型测试:test/typescript 目录包含对storedispatchmiddlewarereducerscompose等类型定义的类型级断言(.test-d.ts);
  • 运行命令(见 package.json):yarn test(vitest 运行 + 类型检查)、yarn test:watch(监听模式)、yarn test:cov(覆盖率)、yarn build(tsup 打包产物到dist/);
  • 示例应用examples/下每个子目录都是独立可npm install后运行的完整应用,其中 examples/testAll.js 可批量跑所有示例的测试。

何时该用 Redux(以及何时不该用)

README 特别提醒(原文核心思想):不要因为别人说该用就用 Redux,请花时间理解使用它的潜在收益与权衡。以下是官方给出的"适合使用 Redux"的参考信号:

  • 有相当数量的数据随时间变化;
  • 需要状态的单一可信来源(single source of truth);
  • 发现把所有状态放在顶层组件里已不再够用。

官方也承认这些标准主观且模糊——这恰恰是因为"何时引入 Redux"因人而异、因应用而异。深入的哲学讨论可参见:

  • Redux FAQ:何时该用 Redux;
  • docs/understanding/history-and-design/PriorArt.md(Redux 的设计前史)与 docs/understanding/thinking-in-redux/ThreePrinciples.md(三大原则:单一数据源、state 只读、纯函数修改)。

帮助与讨论

官方答疑渠道(README 原文):Reactiflux Discord 社区的#redux频道是所有关于学习与使用 Redux 问题的官方资源;你也可以在 Stack Overflow 上使用#redux标签提问;遇到 bug 或需要反馈时,可在 GitHub 仓库提交 issue。

其他仓库信息

  • Logo:官方 Logo 位于仓库 logo/ 目录(含 SVG 与多尺寸 PNG)。
  • Change Log:项目遵循 Semantic Versioning。
  • License:本项目使用 MIT 许可。
  • 开发环境:仓库使用 Yarn 4(packageManager: yarn@4.4.1,见 package.json),源码为 TypeScript,构建工具为 tsup(见 tsup.config.ts)。

结语

Redux 的核心思想极其精炼——单一 store、plain object action、纯 reducer 不可变更新——这三件事构成了"可预测状态管理"的全部基础(docs/understanding/thinking-in-redux/Glossary.md 提供了完整的术语表)。今天,官方强烈建议用 Redux Toolkit 编写所有 Redux 逻辑:代码更少、更安全、类型体验更好;而redux核心包依然可用,是理解底层原理的最佳教材。从本仓库的 examples 示例出发,配合 docs 目录下的官方教程,即可在几小时内完成从概念到实战的完整闭环。

【免费下载链接】reduxA JS library for predictable global state management项目地址: https://gitcode.com/gh_mirrors/re/redux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询