将actionType声明为ES6新增加的Symbol数据类型
当配合react使用redux技术栈时,当应用很大,actionType很多时,如果actionType的数据类型String类型,会出现actionType冲突的情况,“冲突”的意思是,多个reducer可以处理同一个action,但并不是说action和reducer必须要一对一的关系,有些情况下,需要多个reducer处理同一个action。举例:A和B页面定义各自的reducer如下:
//pageA/reducer.js
//pageB/reducer.js
function setTab(state = {
tab: ''
}, action) {
switch(action.type) {
case 'setTab': {
return Object.assign({}, state, {tab: action.tab});
};
default:
return state;
}
}
上面是应用中一个reducer纯函数,根据不同的actionType执行不同的case。好,现在页面A和B各自在自己的目录中创建一个action.js文件,分别定义各自要dispatch的actionCreator,如下:
同事A写的A页面,定义了A页面的一个actionCreator如下:
//pageA/action.js
export const setTab = (tab) => ({type: 'setTab', tab});
同事B写的B页面,定义了B页面的一个actionCreator如下:
//pageB/action.js
export const setTab = (tab) => ({type: 'setTab', tab});
当A页面dispatch``setTab这个actionCreator时,本意是想要执行pageA/reducer.js中的setTab的case,结果因为actionType相同,pageB/reducer.js中的setTab的case也会执行。
解决方案:
- 如果
actionType是String类型,那么对于中小型应用,可以使用命名空间的方式来定义actionType,例如:
export const someActionCreator = () => ({type: `${routeName}_setTab`});
- 但对于大型应用,使用
ES6新增的Symbol数据类型来定义actionType是一种比较好的方案,因为Symbol类型的值都是独一无二的。
对于上面的例子,在A和B页面目录下创建一个actionTypes.js文件,例如:
//pageA/actionTypes.js
export const SET_TAB = Symbol('SET_TAB');
//pageB/actionTypes.js
export const SET_TAB = Symbol('SET_TAB');
在各自的actions.js文件中使用actionTypes.js文件中定义的actionType:
//pageA/actions.js
//pageB/actions.js
import {SET_TAB} from './actionTypes.js';
export const setTab = (tab) => ({type: SET_TAB, tab});
在各自的reducer.js文件中使用actionTypes.js文件中定义的actionType:
//pageA/reducer.js
//pageB/reducer.js
import {SET_TAB} from './actionTypes.js';
function setTab(state = {
tab: ''
}, action) {
switch(action.type) {
case SET_TAB: {
return Object.assign({}, state, {tab: action.tab});
};
default:
return state;
}
}
以上就是我在实际使用react中的一些小总结。