redux-effect-models v1.5.0
redux-effect-models
如果你使用过 dva
或者 vuex
很容易就能理解这是什么。
此插件没有改变 redux
,只是提供了一种不同于官方推荐的数据流构建方式。
采用了以 Model
为单位,将数据分割成多个模块进行管理,每个 Model
负责管理好自己的内部状态,降低了数据流管理的复杂度。
- 支持
Typescript
- 支持 异步
Action
- 支持 中间件
- 支持 动态添加
Model
安装
$ yarn add redux-effect-models
或者
$ npm i redux-effect-models
使用
- 创建一个最简单的
Model
// src/store/models/counter.js
export default {
namespace: 'counter',
state: {
count: 0,
},
effects: {
async addCount(context, action) {
await context.delay(300);
context.dispatch({
type: 'saveCount',
payload: context.state.count + action.payload
})
}
},
reducers: {
saveCount(state, action) {
return {
...state,
count: action.payload,
};
},
},
}
- 调用
reduxEffectModels
初始化状态
// src/store/models/index.js
import { reduxEffectModels } from 'redux-effect-models';
import counter from './counter';
const { reducer, state, effect } = reduxEffectModels([counter]);
export {
// Redux Reducer
reducer,
// 所有 `Model State` 合并出的初始状态
state,
// Redux Middleware
effect
}
- 创建
Redux Store
时, 将调用reduxEffectModels
返回的reducer
state
effect
传入createStore
// src/store/index.js
import { createStore, applyMiddleware } from 'redux';
import { reducer, state, effect } from './models';
const store = createStore(reducer, state, applyMiddleware(effect));
export default store;
- 修改
store
中的状态,action type
就是Model
的namespace
+/
+key
// xxx.js
import store from './store';
console.log(store.getState().counter.count) // 0
// 触发一个 reducer
store.dispatch({
type: 'counter/saveCount',
payload: 100,
});
console.log(store.getState().counter.count) // 这个时候 counter 中的 count 等于 100
// 触发一个 effect 会返回一个 Promise
const p = store.dispatch({
type: 'counter/addCount',
payload: 100,
});
p.then(() => {
console.log(store.getState().counter.count) // 这个时候 counter 中的 count 等于 200
})
概念
Model
Model
完整结构如下所示
{
namespace: string; // 用于识别当前 Model
state: { [key: string]: any }; // 用于合并 rootState
middlewares?: { [key: string]: Middleware[] }; // 用于处理通用异步逻辑
effects?: { [key: string]: Effect }; // 用于处理异步逻辑
reducers: { [key: string]: Reducer }; // 用于同步修改状态
}
Reducer
类型: (state, action) => Object
Reducer
必须是一个纯函数, 修改状态的唯一方式是提交一个 Reducer
, 接收 state
和 action
两个参数, 返回修改后的状态
reducers: {
test(state, action) {
return {
...state,
value: action.payload
}
}
}
Effect
类型: (context, action) => Promise<void>
context
{
namespace, // 当前 Model 的 namespace
state, // 当前 Model 的 state
rootState, // 所有 Model 的 state
dispatch, // action type 自动拼接上当前 Model 的 namespace
rootDspatch, // 原始 dispatch
delay, // 延时器
}
Effect 用于处理异步逻辑,必须返回一个 Promise。可以包含任意异步操作,比如异步请求。在 Effect 中想要修改状态,只能通过提交 Reducer 完成。
effects: {
async test(context, action) {
// 可以触发 reducer 修改状态
context.dispatch({
type: 'reducer'
});
// 也可以触发其他的 effect
await context.dispatch({
type: 'effect'
});
}
}
Middleware
类型: (context, action, next) => Promise<void>
Middleware 用于处理通用异步逻辑,必须返回一个 Promise
,接收 context
action
next
参数。全局中间件会作用于所有 Effect
,Model
内部中间件只会作用于指定的 Effect
。多个中间件执行顺序: 从左到右,从全局到局部,数据流向遵循洋葱模型。
- 完成一个最简单的中间件
async function middleware(context, action, next) {
console.log('start'); // 前置逻辑
await next(); // 必须调用 next 执行后续的 middleware 或者 effect
console.log('end') // 后置逻辑
}
- 全局使用
import { addMiddlewares } from 'redux-effect-models';
addMiddlewares([middleware]);
Model
内使用,Middleware key
和被作用的Effect key
必须保持一致
middlewares: {
test: [middleware] // key = test
},
effects: {
async test() { // key = test
...
}
}
API
reduxEffectModels(models, middlewares?)
参数
reduxEffectModels
接收两个参数
models
:Model
组成的数组(必传)middlewares
: 全局Middleware
组成的数组(可选)
import { reduxEffectModels } from 'redx-effect-models';
const { reducer, state, effect } = reduxEffectModels([model1, model2, model3, ...], [middleware1, middleware2, middleware3, ...]);
返回值
reduxEffectModels
返回含有 reducer
state
effect
这三个属性的对象, 这三个属性都是 Redux createStore()
的参数
reducer
: Redux Reducerstate
: 所有Model State
合并出的初始状态effect
: Redux Middleware
import { createStore, applyMiddleware } from 'redux';
const store = createStore(reducer, state, applyMiddleware(effect));
registerModel(model)
参数
model
需要注册的 Model
import { ActionType, registerModel } from 'redux-effect-models';
registerModel(model);
// 注册后需要调用 dispatch 同步数据
store.dispatch({
type: ActionType.REGISTER
});
unregisterModel(namespace)
参数
namespace
需要被取消注册 Model 的 namespace
import { ActionType, unregisterModel } from 'redux-effect-models';
unregisterModel(namespace);
// 取消注册后需要调用 dispatch 同步数据
store.dispatch({
type: ActionType.UNREGISTER
});
addMiddleware(middleware)
参数
middleware
需要添加的 Middleware
import { addMiddleware } from 'redux-effect-models';
addMiddleware(middleware);
removeMiddleware(middleware)
参数
middleware
需要删除的 Middleware
import { removeMiddleware } from 'redux-effect-models';
removeMiddleware(middleware);
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago