用于管理模块内多个Reducer的模式[Redux]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于管理模块内多个Reducer的模式[Redux]相关的知识,希望对你有一定的参考价值。
我是Redux的新手,我正在尝试找出一种可扩展的方法来设置我的项目文件夹/文件结构。
让我们说我们有一个如下所示的文件结构:
根/模块/托多斯/减速
在项目的根目录中存在一个'rootReducer.js'文件,它使用'combineReducers()'来创建状态树的顶级实现:
[rootReducer.js]
import { combineReducers } from 'redux';
import todos from './modules/Todos/reducers/index.js';
export default combineReducers({
todos: todos
});
每个模块的'redurs'文件夹内有多个reducer:
[root/modules/Todos/reducers]
>index.js
>Todos__addItem
>Todos__removeItem
'index.js'文件导入该模块的所有Reducer并导出单个对象:
[index.js]
import { combineReducers } from 'redux';
import addItem from './Todos__addItem.js';
import removeItem from './Todos__removeItem.js';
export default const todos = combineReducers({
addItem: addItem,
removeItem: removeItem
});
这是'combineReducers()'的正确用法吗?
在开发大规模应用程序时,这种模式是否有意义?
这种模式带来了什么(如果有的话)潜在的陷阱?
谢谢!
这绝对不是combineReducers
的正确用法。 combineReducers
用于将特定状态切片的管理委托给给定函数。您的示例实际上会创建名为addItem
和removeItem
的状态切片,当您真正想要做的是根据调度的动作以不同方式更新相同的todos
状态切片。
我实际上正在为Redux文档编写一个关于“构建减速器”主题的新部分。您可能想要阅读当前的WIP草案 - 其中一些可能有所帮助。该草案可在https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md获得。一些示例应与您的问题相关。
来自https://github.com/suin/redux-multiple-reducers-example的例子
import {counter1, counter2 } from "../../reducers/index"
import CounterApp from "../containers/CounterApp";
const rootReducer = combineReducers({
one:counter1 ,
two:counter2
});
const store = createStore(rootReducer);
class App extends React.Component{
render() {
return (
<Provider store={store}>
<CounterApp />
</Provider>
);
}
Counter1视图
import * as counter1Actions from "../../actions/counter1Actions";
@connect(state => ({
counter1: state.one
}))
export default class Counter1 extends React.Component{
static propTypes = {
counter1: PropTypes.number.isRequired
}
componentDidMount() {
console.info("counter1 component did mount.");
}
onClick() {
console.info("counter1 button was clicked.");
const action = bindActionCreators(counter1Actions, this.props.dispatch);
action.increment();
}
render() {
return (
<div>
<h1>Counter 1</h1>
<button onClick={::this.onClick}>increment</button>
<div>Total: <span>{this.props.counter1}</span></div>
</div>
);
}
}
Counter2观点
import * as counter2Actions from "../../actions/counter2Actions";
@connect(state => ({
counter2: state.two
}))
export default class Counter2 extends React.Component {
static propTypes = {
counter2: PropTypes.number.isRequired
}
componentDidMount() {
console.info("counter2 component did mount.");
}
onClick() {
console.info("counter2 button was clicked.");
const action = bindActionCreators(counter2Actions, this.props.dispatch);
action.increment();
}
render() {
return (
<div>
<h1>Counter 2</h1>
<button onClick={::this.onClick}>increment</button>
<div>Total: <span>{this.props.counter2}</span></div>
</div>
);
}
}
CounterApp
import Counter1 from "../components/Counter1";
import Counter2 from "../components/Counter2";
class CounterApp extends React.Component{
render() {
return (
<div>
<Counter1/>
<Counter2/>
</div>
);
}
}
减速器
export default function counter1(state = initialState, event) {
switch (event.type) {
case "COUNTER1_INCREMENTED":
console.info(`counter1 ack ${event.type}: event =`, event);
return state + 1;
default:
console.warn("counter1 ack unknown event: state =", state, "event =", event);
return state;
}
export default function counter2(state: Object = initialState, event: Object): Object {
switch (event.type) {
case "COUNTER2_INCREMENTED":
console.info(`counter2 ack ${event.type}: event =`, event);
return state + 1;
default:
console.warn("counter2 ack unknown event: state =", state, "event =", event);
return state;
}
}
以上是关于用于管理模块内多个Reducer的模式[Redux]的主要内容,如果未能解决你的问题,请参考以下文章
react状态管理器(分模块)之redux和redux + react-redux + reducer和redux + react-redux + reducer分模块 + 异步操作redux-thu