如何手动用 compose 组合 applyMiddleware 与 DevTools enhancer 创建 Redux store

发布时间:2026/9/9 13:44:19

如何手动用 compose 组合 applyMiddleware 与 DevTools enhancer 创建 Redux store 如何手动用 compose 组合 applyMiddleware 与 DevTools enhancer 创建 Redux store【免费下载链接】reduxA JS library for predictable global state management项目地址: https://gitcode.com/gh_mirrors/re/redux当你不使用 Redux Toolkit 的configureStore而是直接调用原生的createStore时会遇到一个限制createStore(reducer, preloadedState?, enhancer?)的第三个参数只接受一个store enhancer而 Redux 自带的唯一 enhancer 是applyMiddleware()。如果你还想同时接上 Redux DevTools它也是一个 enhancer就必须用compose把多个 enhancer 组合成一个再传给createStore。本文覆盖这条手动组合路径安装依赖、写出compose(applyMiddleware(...), DevTools.instrument())形式的 store 配置并给出仓库 real-world 示例中 dev/prod 分离的完整做法和验证方式。先说清楚适用边界docs/api/compose.md和docs/api/applyMiddleware.md都明确提示你不应该在一般项目里直接调用compose/applyMiddleware——Redux Toolkit 的configureStore会自动配置好标准applyMiddleware和 Redux DevTools enhancer并提供enhancers参数传递额外 enhancer。手动组合这条路主要服务于存量 legacy 代码库的维护或需要完全自定义 store 装配方式的场景。准备安装依赖在 docs/introduction/Installation.md 中安装redux核心包的方式是# NPM npm install redux # Yarn yarn add redux文档同时建议生态中不少包不提供 UMD 构建推荐配合模块打包工具Vite、Webpack 等使用。本文用到的额外包名均出自仓库示例与 API 文档的导入语句npm install redux-thunk # thunk 中间件compose.md 示例使用 npm install redux-logger # real-world 示例中的 createLogger npm install redux-devtools redux-devtools-log-monitor redux-devtools-dock-monitor其中redux-devtools、redux-devtools-log-monitor、redux-devtools-dock-monitor三个包名来自 real-world 示例的 DevTools 容器 的 import 语句仅在你需要文档式 DevTools 界面时才需要安装。核心用 compose 把多个 enhancer 合并成一个先明确三个 API 各自的角色以下事实来自 docs/api/createStore.md、docs/api/applyMiddleware.md 与 docs/api/compose.mdapplyMiddleware(...middleware)本身是一个 store enhancer其签名是createStore createStore最简单的用法是把它作为最后一个enhancer参数传给createStore()原生createStore默认不认识 middleware必须通过applyMiddleware给它加上这个能力compose(...functions)是一个函数式工具从右向左组合函数最右侧函数提供组合后函数的参数签名。源码注释src/compose.ts说明了其语义compose(f, g, h)等价于(...args) f(g(h(...args)))。因此组合多个 enhancer 的标准写法是把applyMiddleware的结果和 DevTools 的 enhancer 一起传给compose。这是compose.md给出的示例import { createStore, applyMiddleware, compose } from redux import { thunk } from redux-thunk import DevTools from ./containers/DevTools import reducer from ../reducers const store createStore( reducer, compose(applyMiddleware(thunk), DevTools.instrument()) )注意compose(applyMiddleware(thunk), DevTools.instrument())的返回结果是一个函数正好填入createStore的单一enhancer参数位置。代码中./containers/DevTools与../reducers是文档示例中的相对路径落到你自己的项目时按实际文件位置调整。组合顺序applyMiddleware 必须排在前面applyMiddleware.md的 Tips 部分有一条明确的顺序要求如果你除了applyMiddleware还使用其他 store enhancer务必让applyMiddleware排在组合链的前面因为 middleware 可能是异步的。文档给出的理由是如果把 DevTools 放在前面DevTools 看不到 Promise 类 middleware 发出的原始 action所以应该写成compose(applyMiddleware(...), DevTools.instrument())这样的顺序而不是反过来。完整做法real-world 示例的 dev/prod 分离配置仓库的 real-world 示例 展示了把这套手动组合用于实际项目时的组织方式核心文件是 configureStore.dev.jsimport { createStore, applyMiddleware, compose } from redux import { thunk } from redux-thunk import { createLogger } from redux-logger import api from ../middleware/api import rootReducer from ../reducers import DevTools from ../containers/DevTools const configureStore preloadedState { const store createStore( rootReducer, preloadedState, compose(applyMiddleware(thunk, api, createLogger()), DevTools.instrument()) ) return store } export default configureStore对照上面的最小示例它多了两处内容preloadedState作为createStore的第二个参数用于预加载状态SSR 水合或恢复会话时用到middleware 列表里除了thunk还传入了api该项目自定义的中间件位于 middleware/api和createLogger()以及redux-logger提供的日志能力。如果你没有自定义中间件可以只保留applyMiddleware(thunk)。对应的 DevTools 容器在 containers/DevTools.js 中定义import React from react import { createDevTools } from redux-devtools import LogMonitor from redux-devtools-log-monitor import DockMonitor from redux-devtools-dock-monitor export default createDevTools( DockMonitor toggleVisibilityKeyctrl-h changePositionKeyctrl-w LogMonitor / /DockMonitor )生产构建则完全去掉 DevTools 和调试日志configureStore.prod.js 直接使用applyMiddleware不需要composeconst configureStore preloadedState createStore(rootReducer, preloadedState, applyMiddleware(thunk, api))两个版本由 store/configureStore.js 按环境切换if (process.env.NODE_ENV production) { module.exports require(./configureStore.prod) } else { module.exports require(./configureStore.dev) }如果想在运行时条件性地加入调试中间件applyMiddleware.md还给出了一种按process.env.NODE_ENV组装中间件数组的写法其中a、b、some-debug-middleware、another-debug-middleware均为文档中的占位示例值需替换为你自己的中间件let middleware [a, b] if (process.env.NODE_ENV ! production) { const c require(some-debug-middleware) const d require(another-debug-middleware) middleware [...middleware, c, d] } const store createStore( reducer, preloadedState, applyMiddleware(...middleware) )文档指出只在需要时 import 调试中间件可以让打包工具裁掉这些模块减小构建体积。验证 store 是否按预期工作文档给出的验证手段有两个1. 用自建 logger 中间件观察 dispatch 链路。applyMiddleware.md的 Custom Logger Middleware 示例展示了 middleware 签名({ getState, dispatch }) next action的最小实现import { createStore, applyMiddleware } from redux import todos from ./reducers function logger({ getState }) { return next action { console.log(will dispatch, action) // Call the next dispatch method in the middleware chain. const returnValue next(action) console.log(state after dispatch, getState()) return returnValue } } const store createStore(todos, [Use Redux], applyMiddleware(logger)) store.dispatch({ type: ADD_TODO, text: Understand the middleware })文档示例输出非固定预期取决于你的 reducer 与状态will dispatch: { type: ADD_TODO, text: Understand the middleware } state after dispatch: [ Use Redux, Understand the middleware ]看到 dispatch 前后的两条日志说明 middleware 链已生效并包裹了dispatch。2. 用store.getState()检查状态。createStore.md的示例演示了最直接的状态核对console.log(store.getState()) // [ Use Redux, Read the docs ]在接了 DevTools 的 dev 配置下DevTools.instrument()会让上述 action 进入 DevTools 界面compose.md对该示例的描述即用applyMiddleware与 redux-devtools 包的若干开发者工具增强 store可在 DockMonitor 的 LogMonitor 中查看 action 记录。限制说明与下一步createStore自 Redux 4.2.0 起被标记为deprecated。这只是视觉上的删除线没有运行时错误或警告createStore会一直保留、不会被移除。如果不想看到删除线可以改用import { legacy_createStore as createStore } from redux的别名导入见 createStore 文档。Redux 官方建议所有应用转向 Redux Toolkit 的configureStore它自动完成本文描述的applyMiddleware DevTools 装配。如果你的目标是改造存量 legacy 代码库可参考 Migrating to Modern Reduxcompose本身的定位也见 docs/api/compose.md。【免费下载链接】reduxA JS library for predictable global state management项目地址: https://gitcode.com/gh_mirrors/re/redux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/9 13:39:18

软件测试工程师转型量子计算:2026认证路径与实战指南

开头先聊个现象。我身边不少做软件测试的朋友,这两年聊天话题越来越集中在“测试这行还能干多久”上。业务功能测试需求确实在收缩,AI辅助编码又在改写整个研发链条,岗位的护城河被一层层削平。但与此同时,另一个方向正静悄悄地打…

2026/9/9 13:39:18

能源行业采购新生态:打印耗材如何撬动非生产性物资数字化变革

前几天刷到一条消息:格之格出现在京东举办的能源行业采购主题会议上,主题直指“能源行业采购新生态”。乍一看,这不过是品牌方参加了一次平台活动,但仔细琢磨,这个话题背后藏着不少值得展开的东西——一个是深耕打印耗…

2026/9/9 14:39:31

Hermes WebUI 数据库集成实战:3 步接入外部数据源

Hermes WebUI 数据库集成实战:3 步接入外部数据源 【免费下载链接】hermes-webui Hermes WebUI: The best way to use Hermes Agent from the web or from your phone! 项目地址: https://gitcode.com/GitHub_Trending/he/hermes-webui AI 助手答得再准&…

2026/9/9 14:39:31

电子名片二维码完全指南:从vCard设计到批量生成实战

二维码这东西,说简单真简单,一个黑白方块图,手机扫一下就能跳转信息;但要是想做得专业、做得好看、扫出来不丢面子,里面的门道还真不少。我最近刚给一个朋友的公司做了一套电子名片二维码,从个人名片到企业…

2026/9/9 14:39:31

服务端测试开发必备:Mock测试原理、实践与踩坑指南

我到现在还记得第一次被联调环境堵到怀疑人生的那天。当时要测一个下单链路,从网关到订单服务、库存服务、优惠券服务,库存服务的同事说接口还在改,优惠券服务直接没发版,我在工位上等了一下午什么都干不了。后来一位老测试开发跟…

2026/9/9 14:34:30

RESTler+Jenkins:API模糊测试流水线实践与踩坑指南

我先把话放这儿:不要指望手工测试能把一个API服务所有角落都测干净。绝大多数团队在CI阶段跑的是Postman集合和单元测试,但等接口文档膨胀到几十个资源、几百个参数组合的时候,人肉构造用例的天花板就到了。我经历过一次线上事故,…

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/8 7:15:10

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/9 0:00:48

MHS模型硬件标准:让大模型像调用软件一样控制物理设备

让Claude真正看着显微镜说“这个细胞形态不太对”,或者让大模型自己调一版机械臂的运动轨迹,这事儿听上去已经很接近科幻片了。但你真上手试一次就会发现,模型不缺智商,缺的是一个能插进显微镜、机械臂、激光控制器里的“通用插座…

2026/9/9 0:00:48

AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?

会有人告诉我,他想转行学AI,但打开招聘网站一看直接傻眼:机器学习、深度学习、自然语言处理、计算机视觉、大模型应用……满屏都是这些词,好像每个都会一点,又好像每个都离自己很远。还有人上来就问“学Python还是学Ja…

2026/9/9 0:00:49

从50行最小循环到生产级AI引擎:工程化改造全解析

直接说干货。这一章我写的不是那种"hello world跑通某个模型"的教程,而是把AI引擎当做一个真正要上线、要被人调用、要扛流量的系统来聊。从最初只有50行的最小循环,到能够承载生产流量的AI引擎,中间差的不是代码量,而是…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码