我正试图围绕如何在redux中更改深层嵌套状态。对我来说,组合减速器并改变这些部件的状态的第一级属性是有意义的。我不太清楚的是如何改变深层嵌套属性的状态。 让我们假装我有一个购物车应用程序。以下是我的状态:
{
cart: {
items: []
},
account: {
amountLeft: 100,
discounts: {
redeemed: [],
coupons: {
buyOneGetOne: false
}
}
}
}
当用户输入代码时,假设他们可以兑换“buyOneGetOne”优惠券,该值应该成立。 我有一个推车减速器和另一个帐户。对于一级房产(如果我清理了购物车的物品),我会在减速机中执行以下操作:
case 'EMPTY_CART':
return Object.assign({}, state, {items: []});
然而,为了改变buyOneGetOne,似乎我首先需要在优惠券上做一个Object.assign(因为buyOneGetOne被修改),然后在折扣上做一个Object.assign(因为我修改过优惠券),然后最后发出动作使减速器可以对帐户进行Object.assign(因为折扣现在已经改变)。然而,这似乎非常复杂且容易出错,这使我相信必须有更好的方法。
我是否认为这一切都错了?似乎reducer仅用于修改状态的根级属性(如购物车和帐户),并且我不应该有一个涉及帐户内部状态的减速器(如折扣减少器),因为帐户已经有减速器。但是当我只想在状态树下更改一个属性时,将每个对象从对象链中的每个对象合并到根的子节点都变得很复杂......
你能/你应该在减速器里面有减速器吗,比如在这种情况下有减速器吗?
答案 0 :(得分:31)
你绝对可以在减速器内部使用减速器;事实上,redux演示应用程序执行此操作:http://redux.js.org/docs/basics/Reducers.html。
例如,您可以创建一个名为`discounts'的嵌套reducer:
function discounts(state, action) {
switch (action.type) {
case ADD_DISCOUNT:
return state.concat([action.payload]);
// etc etc
}
}
然后在帐户缩减器中使用此reducer:
function account(state, action) {
switch (action.type) {
case ADD_DISCOUNT:
return {
...state,
discounts: discounts(state.discounts, action)
};
// etc etc
}
}
要了解详情,请查看Dan本人的egghead.io redux series,特别是reducer composition视频!
答案 1 :(得分:4)
你应该为每个级别
嵌套combinedReducers
答案 2 :(得分:0)
是的,将这些减速器分开是正确的。实际上,如果你害怕其中一些动作需要改变其他减速器,你可以对其他常数做出反应,或者只是发出另一个动作。
I've created a library解决此问题 - 允许简单的合成,并避免冗长的语法,以及合并结果。 所以,你的例子看起来像这样:
import { createTile, createSyncTile } from 'redux-tiles';
const cartItems = createSyncTile({
type: ['account', 'cart'],
fn: ({ params }) => ({ items: params.items })
});
const coupons = createSyncTile({
type: ['account', 'coupons'],
fn: ({ params }) => params,
});
const reedemedCoupons = createSyncTile({
type: ['account', 'reedemedCoupons'],
fn: ({ params }) => params.coupons
});
const account = createTile({
type: ['account', 'info'],
fn: ({ api }) => api.get('/client/info')
});
使用此策略,每个组件都是原子的,您可以轻松地创建新组件并调度其他组件,而不会影响其他组件,这样可以在以后更轻松地重构和删除某些功能,当您的" tile"遵循单一责任原则。