- 前端
【免费下载链接】easy-peasy
Vegetarian friendly state for React
easy-peasy 的createStore产出的本质上是标准 Redux store,因此它可以与官方react-redux包完全共存。本文以仓库文档 usage-with-react-redux.md 为核心,结合 create-store.js、actions.js、hooks.js 等源码实现与 react-redux-compat.tsx 等类型测试,讲解如何在既有react-redux应用中逐步引入 easy-peasy、如何在 Class 组件里借助useDispatch/useSelector消费 easy-peasy store,以及两种 Hook 体系并存的正确姿势。
为什么 easy-peasy 能与 react-redux 直接互通
混用的前提是:easy-peasy 创建的就是一个标准 Redux store。这一点在源码中有直接证据:
- create-store.js 内部调用 Redux 官方
legacy_createStore来构造 store,并传入 reducer、初始状态与由applyMiddleware组合的 enhancer; - actions.js 中,每个 action creator 最终都会调用
_r.dispatch(action),把{ type, payload, config }形式的普通 action 对象交给 Redux dispatch 流程; - hooks.js 中的
useStoreDispatch直接返回store.dispatch,与 Redux 的 dispatch 是同一对象。
因此,任何期待一个 Redux store 的库——尤其是react-redux的Provider、useSelector、useDispatch、connect——都能直接接收 easy-peasy 的 store 实例。官方文档 primary-api.md 也专门强调了这一点:store 实例本质是"带少量增强的 Redux store",可与react-redux的Provider直接配合。
典型应用场景
- 渐进式迁移遗留应用:将一个基于
react-redux构建的老项目逐步迁移到 easy-peasy,无需一次性重写全部状态逻辑; - 连接 Class 组件:通过
useDispatch与useSelector让 easy-peasy store 服务于仍使用 Class 组件的代码; - 混合协作:easy-peasy 的模型与既有 Redux reducer 长期并存(详见姊妹篇 interop-with-existing-react-redux-app.md)。
第一步:安装 react-redux
npm install react-redux在 easy-peasy 仓库内部,react-redux(当前版本^9.2.0)作为 devDependency 被用于互操作性验证,参见 package.json;类型层面还引入了@types/react-redux用于 TypeScript 兼容测试,参见 package.json。
第二步:用 Provider 包裹应用
创建 easy-peasy store 之后,把它交给react-redux的Provider即可:
import React from 'react'; import { render } from 'react-dom'; import { createStore } from 'easy-peasy'; import { Provider } from 'react-redux'; // 👈 导入 Provider import model from './model'; import TodoList from './components/TodoList'; // 👇 创建 store const store = createStore(model); const App = () => ( // 👇 将 store 传给 Provider <Provider store={store}> <TodoList /> </Provider> ); render(<App />, document.querySelector('#app'));仓库的类型测试 react-redux-compat.tsx 验证了这一做法的类型安全性:createStore<StoreModel>(...)产出的 store 可以直接放进react-redux的Provider的store属性。
第三步:用 useSelector 与 useDispatch 连接组件
连接后,组件内就可以使用react-redux的标准 Hook 读取状态、派发动作:
import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; // 👈 从 react-redux 导入 import { addTodo } from './model'; const TodoList = () => { const todos = useSelector(state => state.todos.items); // 读取状态 const dispatch = useDispatch(); // 获取 dispatch return ( <div> {todos.map(({ id, text }) => ( <Todo key={id} text={text} /> ))} <AddTodo onSubmit={(text) => dispatch(addTodo(text))} /> </div> ); }; export default TodoList;需要特别说明的是:原文档第三步的示例代码存在笔误(useSelector与useStoreActions混写、todos/addTodo变量重复声明)。上面给出的是可实际运行的正确写法——在react-redux模式下统一使用useSelector读取状态,通过dispatch(actionCreator(payload))派发 easy-peasy action。easy-peasy 的 action creator 本身就是返回 action 对象的普通函数(见 actions.js),所以完全兼容 Redux 的 dispatch 约定。
两种 Hook 体系的对应关系
如果你不想完全切换到react-redux的 Hook,也可以在同一应用内自由混用。easy-peasy 自身也提供了能力等价的 Hook(实现见 hooks.js):
| 目标 | react-redux | easy-peasy(hooks.js) |
|---|---|---|
| 读取状态 | useSelector(state => ...) | useStoreState(state => ...)(文档) |
| 派发原始 action | useDispatch() | useStoreDispatch()(文档) |
| 获取模型 action | — | useStoreActions(actions => ...)(文档) |
easy-peasy 的useStoreDispatch返回的就是 Redux 原生dispatch(hooks.js),所以向它派发{ type: 'ADD_TODO', payload: text }这类原始 action 也完全可行。而useStoreState底层基于useSyncExternalStore实现订阅与选择器记忆化(hooks.js),使用体验与useSelector类似,但默认采用严格相等(prev === next)判断是否需要重渲染。
与既有 react-redux 代码的深度互操作
如果希望 easy-peasy 的 Hook 与react-redux的connect在同一应用中共存,需要同时包裹两个 Provider(文档见 interop-with-existing-react-redux-app.md):
import { Provider } from 'react-redux'; import { StoreProvider } from 'easy-peasy'; import store from './store'; const app = ( <Provider store={store}> <StoreProvider store={store}> <App /> </StoreProvider> </Provider> );StoreProvider只是基于 React Context 向子树注入 store(provider.js),与react-redux的 Context 互不干扰,因此嵌套是安全的。仓库的类型测试 react-redux-compat.tsx 同样验证了这种"双 Provider 嵌套 + 共享同一 store 实例"的写法在 TypeScript 下可正常编译。
更进一步,你还可以用connect直接连接 easy-peasy store,并利用 easy-peasy 导出的State泛型获得类型推导:
import { connect } from 'react-redux'; import { State } from 'easy-peasy'; connect((state: State<StoreModel>) => ({ items: state.items, }))(Todos);这一用法由 react.tsx 中的类型测试背书:State<StoreModel>能将 store 状态完整推导为类型安全的 props。
迁移既有 Redux 应用时的建议
在将传统 Redux store 迁入 easy-peasy 时,文档 interop-with-existing-react-redux-app.md 给出的路径是:用 easy-peasy 的reducerAPI 把原有 reducer 直接绑定为模型的顶层节点,再叠加 easy-peasy 自己的模型:
import { createStore, reducer } from 'easy-peasy'; import productsReducer from './reducers/products'; import basketReducer from './reducers/basket'; import loggerMiddleware from './middleware/logger'; const model = { // 不再需要 combineReducers,直接把 reducer 绑定到模型键上 products: reducer(productsReducer), basket: reducer(basketReducer), // 同时可以添加任意 easy-peasy 模型 victory: { msg: 'Easy Peasy + Redux harmony', updateMsg: action((state, payload) => { state.msg = payload; }), }, }; const store = createStore(model, { middleware: [loggerMiddleware], }); export default store;迁移时只需用reducerAPI 绑定要迁移的顶层切片,切片内部的嵌套 reducer 无需改动,也不用替换原有的combineReducers调用。另外注意:easy-peasy 内置了redux-thunk中间件(见 create-store.js 中easyPeasyMiddleware数组),无需再显式配置。整个迁移过程对组件层透明——你的组件依然通过react-redux的useSelector/connect工作,状态逻辑则逐步被 easy-peasy 模型接管。
注意事项
- Selector 返回引用类型时注意重渲染:
useStoreState采用严格相等判断状态是否变化(hooks.js)。若 selector 每次执行都返回新对象/数组(如state.items.map(...)),组件会对任意状态更新重渲染。建议拆分 selector 或使用equalityFn参数,详细说明见 use-store-state.md。 - dispatch 的是普通 action:在
react-redux体系下使用 easy-peasy action 时,记得dispatch(actionCreator(payload)),而不是直接调用 action creator。 - 双 Provider 的顺序无强制要求:
Provider(react-redux)与StoreProvider(easy-peasy)先后顺序均可,二者通过各自独立的 Context 传递 store。
综上,easy-peasy 与react-redux的互操作并非"二选一",而是基于标准 Redux store 这一共同基石上的渐进式协作:老代码继续用useSelector/connect,新逻辑逐步迁移为 easy-peasy 模型,最终实现平滑过渡而无需全量重写。
- 前端
【免费下载链接】easy-peasy
Vegetarian friendly state for React
相关推荐
easy-peasy 实战指南:基于 Redux 的零配置 React 状态管理
easy peasy 实战指南:基于 Redux 的零配置 React 状态管理 Easy Peasy 是 Redux 之上的一层抽象,以 开发者体验 为核心重
前端Easy Peasy与现有React Redux应用的集成指南
Easy Peasy与现有React Redux应用的集成指南 痛点:Redux的复杂性 vs 现代化状态管理需求 你是否还在为Redux的繁琐配置和冗长样板代
前端easy-peasy reducer API 完全指南:在 React 状态模型中接入标准 Redux Reducer
easy peasy reducer API 完全指南:在 React 状态模型中接入标准 Redux Reducer 导读 reducer 是 easy pe
前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考