拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Rematch 入门:以无样板代码的方式构建 Redux 框架的 Redux Store

前端【免费下载链接】rematchThe Redux Framework项目地址https://gitcode.com/gh_mirrors/re/rematch点击查看免费下载本文基于 Rematch 仓库的介绍文档docs/introduction.md展开Rematch 定位为“不带样板代码的 Redux 最佳实践”即无需再手写 action types、action creators、switch 语句和 thunks。读完本文你将理解 Rematch 的完整能力清单、从零初始化 store 的四步流程并能对照 packages/core 的源码确认每一项特性背后的真实实现从而在 React、React Native 等场景中以极小的依赖体积接入 Redux 状态管理。一、Rematch 是什么Redux 是一个强大的状态管理工具拥有健康的中间件生态和出色的 devtools。Rematch 建立在 Redux 之上通过减少样板代码并强制推行最佳实践来解决 Redux 的三大痛点不再需要定义 action types 常量字符串不再需要编写 action creators 函数不再需要 reducer 中的switch分支也不再需要为异步逻辑引入 thunks。README 中的对比表概括了两者的关系摘自 README.md能力ReduxRematch简单搭建支持更少的样板代码支持可读性支持可配置支持支持redux devtools支持支持自动生成的 action creators支持异步处理thunksasync/await需要说明的是Rematch 并没有替代 Redux从 packages/core/package.json 可见rematch/core声明了peerDependencies: { redux: 4 }当前版本为 2.2.0它构建的是一个真实 Redux store只是把配置和调用方式包装得更为简洁。二、官方特性清单与源码印证介绍文档列出了 Rematch 的完整特性下面逐项结合仓库源码给出实现层面的印证。2.1 体积小于 2kb且无需配置介绍文档宣称核心小于 2kbREADME 进一步标注为 less than 1.4 kilobytes。源码规模也确实很小packages/core/src/index.ts 整个入口只导出init、createModel与全部类型定义。“无配置”体现为 packages/core/src/config.ts 中的createConfig用户不传任何参数也能构建完整配置——models默认为{}、plugins默认为[]Redux 侧的reducers、rootReducers、enhancers、middlewares全部有默认值devtoolOptions.name默认取 store 名称。2.2 减少 Redux 样板代码Model 把 state、reducers、effects 聚合在一处。从 packages/core/src/reduxStore.ts 的createModelReducer可以看到样板代码是如何被消解的每个 model 的 reducer 键自动组合为modelName/reducerKey形式的 action name如count/increment完全取代手写 action type 常量生成一个combinedReducer按action.type分发到对应 reducer 并传入state、action.payload、action.meta取代switch语句若 reducer 键本身包含/如监听其他 model 的 action则通过isAlreadyActionName判定后直接作为 action name 使用。2.3 内置副作用effects支持effects 让异步逻辑用原生 async/await 表达。实现分两半dispatcher 侧packages/core/src/dispatcher.ts 的createEffectDispatcher会把effects: (dispatch) ({...})形式的 effects 展开将每个 effect 以modelDispatcher为this绑定后注册进bag.effects[modelName/effectName]并在dispatch[modelName]上挂上带isEffect: true标记的 action 生成器middleware 侧packages/core/src/rematchStore.ts 中的createEffectsMiddleware拦截 action——当action.type in bag.effects时先调用next(action)执行 reducer如果存在同名的 reducer再调用对应 effect 函数并传入action.payload、store.getState()、action.meta返回其结果。这正是“thunks 被 async/await 取代”的底层机制effect 的返回值可以是一个 Promise调用方可以await。2.4 自动生成的 dispatch 与 React Devtools 支持dispatch[model]action的便捷语法由createActionDispatcher生成构造{ type: modelName/actionName, payload?, meta? }后转发给 Redux 的dispatch。Devtools 支持在 packages/core/src/reduxStore.ts 的composeEnhancersWithDevtools中实现只要未通过devtoolOptions.disabled关闭且window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__存在就用扩展提供的 compose 包装增强器devtoolOptions.name默认为 store 名称因此多个 store 在 Devtools 中可区分。2.5 TypeScript 支持packages/core/src/types.ts 提供了完整类型体系Model/NamedModel/Models描述模型结构RematchRootStateTModels从所有 model 的state推导根 state 类型RematchDispatchTModels在原生 ReduxDispatch 之上叠加dispatch[modelName]actionName的签名并根据 reducer/effect 的参数推导payload、meta是否必填effect dispatcher 还会携带isEffect标记与返回类型createModelRootModel()({ ... })辅助函数在 packages/core/src/index.ts 中定义用于在models/index.ts中导出RootModel接口后获得完整的类型推断。2.6 动态添加 reducersRematchStore接口在ReduxStore基础上额外暴露addModel方法。其实现位于 packages/core/src/rematchStore.ts 的rematchStore对象字面量中先validateModel校验、createModelReducer注册 reducer、prepareModel与enhanceModel生成 dispatchers最后调用reduxStore.replaceReducer(createRootReducer(bag))并派发redux/REPLACE触发 Devtools 重算实现运行时动态挂载新 model。2.7 支持热重载与多 store热重载model 以普通模块导出、store 通过init集中创建配合shouldHotReload等 devtool 选项与replaceReducer机制见 2.6HMR 场景下 reducer 可被整体替换而不丢失状态多 storepackages/core/src/config.ts 维护了一个模块级计数器未指定name时自动命名为Rematch Store 0、Rematch Store 1……每次调用init都基于独立配置创建独立 Redux storestore.name会同时用于 Devtools 实例名便于多 store 并存。2.8 支持 React Nativerematch/core对 Redux 的依赖是纯 JS 实现Devtools 接入被typeof window object守卫保护见 packages/core/src/reduxStore.ts非浏览器环境自动回退到Redux.compose因此可直接用于 React Native。2.9 插件可扩展性与官方插件库Rematch 及其内部全部构建在插件管道之上见bag.forEachPlugin的调用点createMiddleware、onModel、onStoreCreated、onReducer、onRootReducer。官方插件一览见 docs/plugins/index.mdImmer 插件用 immer 包装 reducers允许以可变写法产生不可变状态Select 插件为 models 提供 reselect 风格的 selectorsPersist 插件redux-persist 封装持久化数据Loading 插件为 effects 自动添加 loading 指示器Updated 插件记录 model、effect、reducer 最近触发时间另有 typed-state 插件 提供useTypedState等类型化状态访问。官方插件源码均在仓库内可直接阅读例如 packages/loading/src/index.ts 展示了完整插件形态通过config.models注入一个loadingmodel通过onModel钩子包裹每个 effect 的 dispatcher在 Promise 的 then/catch 中派发show/hide更新 loading 状态并支持whitelist/blacklist过滤与boolean/number/full三种状态形态。三、从零开始的四步上手流程以下流程继承自 docs/installation.md是最小可用的完整路径。Step 0安装npm install rematch/core注意redux是 peer 依赖4需要随项目一起安装engines要求 Node10。Step 1定义 modelsModel 回答三个问题初始状态是什么state、如何同步改变状态reducers、如何处理异步effects。export const count { state: 0, // 初始状态 reducers: { // 纯函数处理状态变更 increment(state, payload) { return state payload; }, }, effects: (dispatch) ({ // 非纯函数处理状态变更异步用 async/await async incrementAsync(payload, rootState) { await new Promise((resolve) setTimeout(resolve, 1000)); dispatch.count.increment(payload); }, }), };TypeScript 版本使用createModel辅助函数并在models/index.ts中声明RootModel以获得推断// ./models/count.ts import { createModel } from rematch/core; import { RootModel } from .; export const count createModelRootModel()({ state: 0, reducers: { increment(state, payload: number) { return state payload; }, }, effects: (dispatch) ({ async incrementAsync(payload: number, state) { console.log(This is current root state, state); await new Promise((resolve) setTimeout(resolve, 1000)); dispatch.count.increment(payload); }, }), });// ./models/index.ts import { Models } from rematch/core; import { count } from ./count; export interface RootModel extends ModelsRootModel { count: typeof count; } export const models: RootModel { count };复杂 state 可用as断言给出完整类型仓库中的完整可运行示例见 examples/count-react-ts/src/models/questions.ts 与 examples/all-plugins-react-ts/src/models这些示例全部纳入仓库测试套件examples/all-plugins-react-ts/src/index.test.tsx。Step 2初始化 storeinit是唯一必须调用的方法。最低限度只需提供models// store.js import { init } from rematch/core; import * as models from ./models; const store init({ models }); export default store;// store.ts import { init, RematchDispatch, RematchRootState } from rematch/core; import { models, RootModel } from ./models; export const store init({ models }); export type Store typeof store; export type Dispatch RematchDispatchRootModel; export type RootState RematchRootStateRootModel;Step 3派发 actiondispatch既支持原生 Redux 的dispatch({ type, payload })也支持dispatch[model]action简写两者等价const { dispatch } store; // state { count: 0 } dispatch({ type: count/increment, payload: 1 }); // state { count: 1 } dispatch.count.increment(1); // state { count: 2 } dispatch({ type: count/incrementAsync, payload: 1 }); // 延迟后 state { count: 3 } dispatch.count.incrementAsync(1); // 延迟后 state { count: 4 }Step 4接入视图层Rematch 可与 react-redux 等原生 Redux 集成方式无缝配合// App.js import React from react; import ReactDOM from react-dom; import { Provider, connect } from react-redux; import store from ./store; const Count (props) ( div The count is {props.count} button onClick{props.increment}increment/button button onClick{props.incrementAsync}incrementAsync/button /div ); const mapState (state) ({ count: state.count }); const mapDispatch (dispatch) ({ increment: () dispatch.count.increment(1), incrementAsync: () dispatch.count.incrementAsync(1), }); const CountContainer connect(mapState, mapDispatch)(Count); ReactDOM.render( Provider store{store} CountContainer / /Provider, document.getElementById(root) );examples/count-react 是这套最小用法的完整可运行工程。四、store 创建的内部调用链理解init之后的内部流程有助于在排查问题时定位环节。从 packages/core/src/index.ts 到 packages/core/src/rematchStore.tsinit的调用链为createConfigconfig.ts补齐默认值、校验配置并遍历config.plugins将每个插件config.models、config.redux中的改动合并进主配置模型合并、initialState/reducers 浅合并、enhancers/middlewares 追加、combineReducers/createStore可被插件覆盖createRematchBagbag.ts把models映射转成带name与默认空reducers的命名模型数组并对每个 model 执行validateModel组装 storerematchStore.ts先向bag.reduxConfig.middlewares压入 effects 中间件再依次收集各插件的createMiddleware产物createReduxStorereduxStore.ts为每个 model 生成 combined reducer、合并 root reducer支持rootReducers前置处理、组合 middlewares 与 devtools 增强器后创建真正的 Redux storeprepareModel先为每个 model 注入dispatch[modelName]并生成 reducer dispatchersenhanceModel再生成 effect dispatchers 并触发插件的onModel钩子——两步分离是为了让循环引用模型如示例 packages/core/test/v1_regressions/circurlarmodels.test.ts在 effects 中解构时都能拿到彼此最后执行插件的onStoreCreated钩子允许插件替换或扩展最终 store。相关行为均有测试覆盖例如 packages/core/test/multiple.test.ts多 store、packages/core/test/plugins.test.ts插件管道、packages/core/test/effects.test.tseffects 语义。五、插件 API扩展点的完整清单介绍文档强调 Rematch “Extendable with plugins”其 API 详见 docs/api-reference/plugins.md。一个插件对象可包含config: { models, redux }注入额外 model 或覆盖 Redux 配置形状与init接受的配置一致exposed向 store 挂载额外属性供插件间通信在onModel与onStoreCreated之前执行createMiddleware(bag)创建可访问 Rematch 内部 “bag” 的自定义中间件onReducer(reducer, modelName, bag)model 的 base reducer 创建时执行可返回新 reducer 覆盖onRootReducer(reducer, bag)root reducer 创建时执行可返回新 root reducer 覆盖onModel(namedModel, rematchStore)每个 model 的 reducers 与 dispatchers 就绪后执行动态addModel时也会再次触发onStoreCreated(rematchStore, bag)store 就绪后的最后一个钩子可返回新 store 覆盖。完整形态示例摘自官方插件 API 文档const plugin { config: { redux: { combineReducers: customCombineReducers, }, models: { extra: extraModel, }, }, exposed: { select: {} }, createMiddleware: (rematchBag) (store) (next) (action) { // do something here return next(action); }, onReducer(reducer, modelName, bag) { // do something }, onRootReducer(reducer, bag) { // do something }, onModel(namedModel, rematchStore) { // do something }, onStoreCreated(rematchStore, bag) { // do something }, };这些钩子在核心中的触发点均可在 packages/core/src/rematchStore.ts、packages/core/src/reduxStore.ts 与 packages/core/src/bag.ts 中逐一对应找到forEachPlugin(onReducer | onRootReducer | onModel | onStoreCreated | createMiddleware)。六、进阶路径与资源索引介绍文档为两类读者给出了分岔口来自现有 Redux 代码库迁移往往只涉及状态管理层的小改动视图逻辑基本不动详见 docs/migrating/from-redux.md从零开始先读安装指南 docs/installation.mdTypeScript 用户可直接跳转 docs/typescript.md 了解 utility typesv1 老用户可参考 docs/migrating/from-v1-to-v2.md。仓库内值得深入的路径路径内容packages/core/src核心库全部源码bag、config、dispatcher、reduxStore、rematchStore、types、validatepackages/core/test核心行为测试effects、plugins、multiple、init、listener 等examples10 个可运行示例count-react、count-react-ts、all-plugins-react-ts、multi-react多 store、nextjs-blog、gatsby-example 等docs/api-referenceinit配置参数、models、plugins、redux 配置、store 的完整 API 参考docs/recipesRedux DevTools、Redux 插件、测试等实战配方七、许可与支持项目采用 MIT 许可LICENSE问题反馈、功能请求与疑问可提交 issue对应 CONTRIBUTING.md 中的社区规范版本适用前提本文所述 API 对应仓库中rematch/core2.2.0packages/core/package.json要求redux 4、Node 10文档与示例均以当前仓库内容为准。赞分享前端【免费下载链接】rematchThe Redux Framework项目地址https://gitcode.com/gh_mirrors/re/rematch点击查看免费下载相关推荐Rematch用模型驱动的 Redux 框架消除样板代码从 Model 到 Store 的完整剖析Rematch用模型驱动的 Redux 框架消除样板代码从 Model 到 Store 的完整剖析 本文以 Rematch 仓库根目录 README htt前端Rematch 安装与快速上手用 rematch/core 四步搭建 Redux StoreRematch 安装与快速上手用 rematch/core 四步搭建 Redux Store 本篇基于 Rematch 官方文档的 Installation前端Rematch Store API 详解:在 Redux Store 之上构建对象化 dispatch 与动态 addModelRematch Store API 详解:在 Redux Store 之上构建对象化 dispatch 与动态 addModel Rematch 通过 init前端上一篇SQLAlchemy水平分片(Sharding)实战基于多数据库的分片实现下一篇GraphScope项目常见问题深度解析与技术指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门