【发布时间】:2016-09-30 06:34:24
【问题描述】:
正如the doc 所说:
你不应该在 reducer 中做的事情:
- 改变它的论点;
- 执行 API 调用和路由转换等副作用;
- 调用非纯函数,例如Date.now() 或 Math.random()。
如果我遵循原则,关于代码组织有一些问题(我的应用程序是文件管理器)。
例如,
这样的默认减速器:
export default function (state = initialState, action) {
const { path } = action
if (typeof path === 'undefined') {
return state
}
const ret = {
...state,
[path]: parentNode(state[path], action)
};
switch (action.type) {
case OPEN_NODE:
case GO_PATH:
ret['currentPath'] = path
break
default:
break
}
return ret
}
state[path] 中的数据结构喜欢:
{
'open': false,
'path': '/tmp/some_folder',
'childNodes' : [ {'path':'/some/path', 'mode': '0755', 'isfolder': true}, ....],
'updateTime': Date.now()
}
现在我需要几个动作,例如ADD_CHILD、DELETE_CHILD、RENAME_CHILD、MOVE_CHILD,有两个 sulotions(通过更改动作或减速器的状态):
1。动作中的所有功能代码:
行动:
export function updateChildNodes(path, nodes) {
return {
type: UPDATE_CHILD_NODES,
path: path,
loading: false,
loaded: true,
childNodes: nodes,
};
}
export function addChild(path, node) {
return (dispatch, getState) => {
const state = getState().tree[path]
var childNodes = state.childNodes ? state.childNodes :[]
childNodes.push(node)
return dispatch(updateChildNodes(path, childNodes))
}
}
export function deleteChild(parent_path, child_node) {
return (dispatch, getState) => {
const state = getState().tree[parent_path]
var childNodes = state && state.childNodes ? state.childNodes : []
for (var i=0; i <=childNodes.length; i++){
if (childNodes[i].path == child_node.path){
childNodes.splice(i, 1)
return dispatch(updateChildNodes(parent_path, childNodes))
}
}
}
}
export function deleteNode(node) {
return (dispatch, getState) => {
// ajax call
return api.deleteChild(node.path, () => {
dispatch(deleteChild(node.parent, node))
})
}
}
.....
parentNode 减速器:
function parentNode(state, action) {
switch (action.type) {
case UPDATE_CHILD_NODES:
return {
...state,
childNodes: action.childNodes
}
default:
return state;
}
}
所有变量都从动作传入 parentNode,parentNode 只是将更改分配给 state 不会做任何其他事情。
remove node 和 add node 的所有逻辑都是通过动作完成的,只有parentNode 中的UPDATE_CHILD_NODES。
2。 Action 只是将数据发送给 reducer,让 reducer 处理
行动:
export function updateChildNodes(path, nodes) {
return {
type: UPDATE_CHILD_NODES,
path: path,
loading: false,
loaded: true,
childNodes: nodes,
};
}
export function addChild(path, node) {
return {
type: ADD_CHILD,
path: path,
node: node,
};
}
export function deleteChild(path, node) {
return {
type: DELETE_CHILD,
path: path,
node: node,
};
}
export function deleteNode(node) {
return (dispatch, getState) => {
// ajax call
return api.deleteChild(node.path, () => {
dispatch(deleteChild(node.parent, node))
})
}
}
.....
parentNode 减速器:
function parentNode(state, action) {
switch (action.type) {
case DELETE_CHILD:
let childNodes = state.childNodes.slice() // have to clone obj
for (var i=0; i <=childNodes.length; i++){
if (childNodes[i].path == action.node.path){
childNodes.splice(i, 1)
}
}
return {
...state,
childNodes: childNodes
};
case ADD_CHILD:
let childNodes = state.childNodes.slice() // have to clone obj
childNodes.push(node)
return {
...state,
childNodes: childNodes
};
case UPDATE_CHILD_NODES:
return {
...state,
childNodes: action.childNodes
}
default:
return state;
}
}
在我的选择中,解决方案 2 更具可读性和美观性。
但是通过变异一个克隆的 obj 来改变状态是否很好?当我需要通过Date.now() 设置updateTime 时,我必须从动作中生成它并传递给reducer,以便在不同的地方生成状态变量(但我想把它们放在一起......)
对此有何看法?
【问题讨论】:
标签: javascript reactjs ecmascript-6 redux react-redux