Javascript 如何使用嵌套对象编写状态缩减器
我的redux状态树的心智模型如下所示:Javascript 如何使用嵌套对象编写状态缩减器,javascript,redux,Javascript,Redux,我的redux状态树的心智模型如下所示: { selectedDepartment: 'Chemistry', purchasesByDepartment: { Chemistry: { purchaseOrders: { ... }, invoices: { ... } }, Biology: { purchaseOrders: { ... }
{
selectedDepartment: 'Chemistry',
purchasesByDepartment: {
Chemistry: {
purchaseOrders: {
...
},
invoices: {
...
}
},
Biology: {
purchaseOrders: {
...
},
invoices: {
...
}
},
...(another department, etc)
}
}
return {
...state,
purchasesByDepartment: {
...state.purchasesByDepartment,
Chemistry: {
...state.purchasesByDepartment.Chemistry,
invoices: {
{your new invoices object comes here}
}
}
}
}
这是我的减速机
const purchasesByDepartment = (state = {}, action) => {
switch (action.type) {
case RECEIVE_POS:
return Object.assign({}, state, {
[action.department]: {
purchaseOrders: action.json
// but this wipes out my invoices
}
})
case RECEIVE_INVOICES:
return Object.assign({}, state, {
[action.department]: {
invoices: action.json
// but this wipes out my purchaseOrders
}
})
default:
return state
}
}
你可以看到,在每个部门,我都有一个采购订单和一个发票密钥。
我正在尽我最大的努力来编写我的reducer,这样它就不会改变我的状态,但我没有运气,因为每个动作目前都会抹去另一个键
我启动两个操作:接收POS、接收发票
当发送我的操作RECEIVE_POS时,我可以为采购订单创建一个新状态,但这会清除我的发票
当发送我的操作接收发票时,我可以使用发票创建一个新状态,但这会清除我的采购订单
如果采购订单和发票在我所在的州已经存在,我如何编写我的缩减器以便保留它们?您可以首先通过应用更改为部门创建新状态,然后将其合并到缩减器状态
const purchasesByDepartment = (state = {}, action) => {
switch (action.type) {
case RECEIVE_POS:
let nextPOS = Object.assign({}, state[action.department] || {}, {
purchaseOrders: action.json
});
return Object.assign({}, state, nextPOS);
default:
return state
}
}
就我个人而言,我喜欢使用immutablejs
使我的整个存储区不可变,这使得这样的操作(以及其他一些事情)变得微不足道:
您可以首先通过应用更改为部门创建新状态,然后将其合并到状态中
const purchasesByDepartment = (state = {}, action) => {
switch (action.type) {
case RECEIVE_POS:
let nextPOS = Object.assign({}, state[action.department] || {}, {
purchaseOrders: action.json
});
return Object.assign({}, state, nextPOS);
default:
return state
}
}
就我个人而言,我喜欢使用immutablejs
使我的整个存储区不可变,这使得这样的操作(以及其他一些事情)变得微不足道:
我使用扩展运算符(表示为…arrayName
)来实现这一点。这是es6,我启用了巴贝尔的功能
Spread
将数组展开到其元素中,其可读性比对象更高。assign
根据您的上下文,对于我的reducer中的一个简单场景,我只想:
return {
...state,
selectedDepartment: 'Chemistry or whatever'
}
这将返回一个由state和selectedDepartment组成的数组,并用给定值覆盖
对于嵌入式对象,可以这样放置:
{
selectedDepartment: 'Chemistry',
purchasesByDepartment: {
Chemistry: {
purchaseOrders: {
...
},
invoices: {
...
}
},
Biology: {
purchaseOrders: {
...
},
invoices: {
...
}
},
...(another department, etc)
}
}
return {
...state,
purchasesByDepartment: {
...state.purchasesByDepartment,
Chemistry: {
...state.purchasesByDepartment.Chemistry,
invoices: {
{your new invoices object comes here}
}
}
}
}
我使用扩展运算符(表示为…arrayName
)来实现这一点。这是es6,我启用了巴贝尔的功能
Spread
将数组展开到其元素中,其可读性比对象更高。assign
根据您的上下文,对于我的reducer中的一个简单场景,我只想:
return {
...state,
selectedDepartment: 'Chemistry or whatever'
}
这将返回一个由state和selectedDepartment组成的数组,并用给定值覆盖
对于嵌入式对象,可以这样放置:
{
selectedDepartment: 'Chemistry',
purchasesByDepartment: {
Chemistry: {
purchaseOrders: {
...
},
invoices: {
...
}
},
Biology: {
purchaseOrders: {
...
},
invoices: {
...
}
},
...(another department, etc)
}
}
return {
...state,
purchasesByDepartment: {
...state.purchasesByDepartment,
Chemistry: {
...state.purchasesByDepartment.Chemistry,
invoices: {
{your new invoices object comes here}
}
}
}
}
对象排列与计算属性名相结合帮助我解决了这个问题
case RECEIVE_POS:
return {
...state,
[action.department]: {
...state[action.department],
purchaseOrders: action.json
}
}
case RECEIVE_INVOICES:
return {
...state,
[action.department]: {
...state[action.department],
invoices: action.json
}
}
对象排列与计算属性名相结合帮助我解决了这个问题
case RECEIVE_POS:
return {
...state,
[action.department]: {
...state[action.department],
purchaseOrders: action.json
}
}
case RECEIVE_INVOICES:
return {
...state,
[action.department]: {
...state[action.department],
invoices: action.json
}
}
我喜欢这个答案。看起来我需要花一些时间检查ImmutableJSI,我喜欢这个答案。看起来我需要花一些时间来检查ImmutableJS您的回答让我想到了使用对象排列与计算属性名称相结合来解决此问题您的回答让我想到了使用对象排列与计算属性名称相结合来解决此问题