Redux毫无疑问是一个模型简洁漂亮,扩展性极佳的状态管理器,但是在其与React整合使用时,我们有时会希望React能与Redux的代码整合起来形成一个可复用的复杂组件,具体的描述可以参见 RFC: Reuse complex components implemented in React plus Redux #278, Redux-Arena就是一个为解决这个问题开发的Redux模块化管理器。
Redux-Arena会将Redux/Redux-Saga的代码与React组件导出成一个React高阶组件以供复用:
- 在高阶组件被挂载(Mount)时,会自动初始化Redux-Saga的任务,初始化组件的reducer并在Redux维护的State上注册自己的节点。
- 在高阶组件被卸载(Unmout)时,会自动取消Redux-Saga的任务,销毁组件的reducer并从Redux维护的State上删除自己的节点。
- 提供组件信道机制,组件发送的Action默认只能被组件自己的reducer接收。也可以通过配置放弃信道,接收全局的action。
- 提供vReducerKey机制,Redux中如果组件间想共享state信息,需要知道知道真实的节点名称,在可复用的Redux组件中很容易引发冲突,Redux-Arena提供vReducerKey机制保证了state节点真实名称永远不会冲突。vReducerKey在同名时,下层组件会覆盖掉上层组件的vReducerKey信息。
- 提供单向的(类似flux的 one-way data flow)组件状态和actions的共享方案,下层组件可以通过vReducerKey获取上层组件的state和actions。
- 与Redux-Saga深度整合,在Redux-Saga中也可以选择只发送和接收组件自己的action。
此外,Redux-Arena还提供了与React-Router的整合方案。
npm install redux-arena --save
/example
目录下包含了一个完整的示例,包括了多个HOC的使用。并且使用了redux-devtool动态展示state的变化。
在线版本的示例点击这里
- 将react组件、actions、reducer、saga 文件导出成React组件
import { bundleToComponent } from "redux-arena/tools";
import state from "./state";
import saga from "./saga";
import * as actions from "./actions";
import PageA from "./PageA";
export default bundleToComponent({
Component: PageA,
state,
saga,
actions
})
- 初始化arenaStore并将其提供给redux。PageA组件是上一步导出的。
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createArenaStore } from "redux-arena";
import PageA from "./pageA";
let store = createArenaStore();
let app = document.getElementById("app");
ReactDOM.render(
<Provider store={store}>
<PageA />
</Provider>,
app
);
为redux-arena创建增强版store
-
reducers: object
- 对象形式的redux的reducer。Example
{ frame: (state)=>state, page: (state)=>state, ... }
-
options: object
- Store的设置选项。initialStates: object
- 对象形式的redux的state。
Example
{ frame: { location:"/" }, page: { cnt:0 }, ... }
-
enhencers: array
- 数组形式的redux enhencers。Example
import { applyMiddleware } from "redux"; import thunk from "redux-thunk"; let enhancers = [applyMiddleware(thunk)];
-
middlewares: array
- 数组形式的redux middlewares。Example
import thunk from "redux-thunk"; let middlewares = [thunk];
-
sagaOptions:object
- redux-saga的扩展选项。
-
enhancedStore:object
- 函数返回值,拥有以下方法:runSaga(saga)
- 开始一个saga任务.
Bundle是一个包含react-component, actions, reducer, saga ,options的对象, 用于ArenaScene高阶组件。
Example
import state from "./state";
import saga from "./saga";
import * as actions from "./actions";
import Component from "./Component";
export default {
Component,
state,
saga,
actions,
options:{
vReducerkey:"vKey1"
}
}
-
Component: React.Component
- 用于绑定Redux的React组件。 -
state: object
- Bundle的初始状态。 -
actions: object
- 与Redux的actions相同,当组件被挂载时初始化。 -
saga: function*
- Redux-Saga的生成器函数,当组件被挂载时初始化。 -
propsPicker: function(stateDict, actionsDict)
- 挑选state与actions到组件的props。$是相对位置表示符号,$0可以快速拿到当前层次的信息,同理$1可以拿到上一层的信息。如果该项为空,默认会将state中的所有实体绑定至同名的props中,并将actions绑定至props的actions中。
Example
import state from "./state";
import saga from "./saga";
import * as actions from "./actions";
import Component from "./Component";
export default {
Component,
state,
actions,
propsPicker:({$0: state}, {$0: actions})=>({
a: state.a,
actions
})
}
-
options: object
- Bundle的选项。-
reducerKey: string
- 为bundle指定reducerKey。 -
vReducerKey: string
- 为bundle指定虚拟reducerKey。 -
isSceneAction: bool
- 如果为false, "_sceneReducerKey"不会添加到发送的action中。 -
isSceneReducer: bool
- 如果为false, reducer会接收其他bundle发送的action。
-
将Bundle转化为组件的帮手函数。
将Bundle转化为element的帮手函数。
获取当前scene的state。
Example
import { setSceneState, takeLatestSceneAction } from "redux-arena/effects";
function * doSomthing({ payload }){
yield setSceneState({ payload })
}
export function* saga (){
yield takeLatestSceneAction("DO_SOMETHING", doSomthing)
}
获取当前scene的state。
发送当前scene的action。
设置当前scene的state。
Example
import { setSceneState, getSceneState } from "redux-arena/effects";
function * doSomthing(){
let { a } = yield getSceneState()
yield setSceneState({ a : a+1 })
}
获取当前scene的每一个action
获取当前scene的最新action
获取当前scene的action