替换深层子对象,同时在 React 中保持状态不可变
Replace deep child object, while keeping state immutable in React
我是 React 和 redux 的新手。我有一个对象是一个子对象数组,其中包含数组
const initialState = {
sum: 0,
denomGroups: [
{
coins: [
{ name: 'Penny', namePlural: 'Pennies', label: '1¢', value: .01, sum: 0 },
{ name: 'Nickel', namePlural: 'Nickels', label: '5¢', value: .05, sum: 0 },
{ name: 'Dime', namePlural: 'Dimes', label: '10¢', value: .10, sum: 0 },
{ name: 'Quarter', namePlural: 'Quarters', label: '25¢', value: .25, sum: 0 }
]
},
{
bills: [
{ name: 'Dollar', namePlural: 'Dollars', label: '', value: 1, sum: 0 },
{ name: 'Five', namePlural: 'Fives', label: '', value: 5, sum: 0 },
{ name: 'Ten', namePlural: 'Tens', label: '', value: 10, sum: 0 },
{ name: 'Twenty', namePlural: 'Twentys', label: '', value: 20, sum: 0 },
{ name: 'Fifty', namePlural: 'Fiftys', label: '', value: 50, sum: 0 },
{ name: 'Hundred', namePlural: 'Hundreds', label: '0', value: 100, sum: 0 }
]
}
]
};
我有一个操作会传递一个值和面额名称
export function increaseSum(value, denom) {
return { type: types.ADD_TO_SUM, value: value, denom: denom }
}
在我的 reducer 内部,我写了一个助手 class 来识别这个面额在对象中的位置:
function findDenomination(denoms, action) {
let denomMap = {},
currentDenom = {};
for (let i = 0; denoms.length >= i + 1; i++) {
let denomGroup = denoms[Object.keys(denoms)[i]];
for (var key in denomGroup) {
if (!currentDenom.length) {
currentDenom = denomGroup[key].filter(x => x.name === action.denom);
if (currentDenom.length > 0) {
denomMap.group = i;
denomMap.key = key;
denomMap.index = denomGroup[key].findIndex(x => x.name === action.denom);
}
}
}
if (currentDenom.length > 0) {
break;
}
}
return denomMap;
}
并且在 reducer 本身中,我使用 Object.assign
来制作 denomGroups 的深度副本,以我认为保持不变的方式。
function countableItems(state = initialState, action) {
switch (action.type) {
case types.ADD_TO_SUM:
let denomMap = findDenomination(state.denomGroups, action);
state.denomGroups = Object.assign({}, state.denomGroups, state.denomGroups[denomMap.group][denomMap.key][denomMap.index].sum = parseFloat(action.value));
return state;
default:
return state;
}
}
有没有人清楚为什么这被标记为错误:A state mutation was detected inside a dispatch
你试图改变一个不可变的。因此错误。
不可变对象的全部要点在于,不可变对象在创建后永远不应该在其内部的任何地方发生变化。这就是为什么所有改变它的函数都会创建一个不可变的新实例。如果你试图改变一个不可变的深处的东西,那仍然是一个突变,因此很糟糕。
这确保您可以只检查对象本身是否相等,而不必进行深入检查,并确保数据完整性。
你应该做的只是改变它(如果你正在使用 immutables
库,你可以使用 setIn
),这将创建一个新的地图。您可以在 state
.
上调用它
像这样:
case types.ADD_TO_SUM:
const denomMap = findDenomination(state.denomGroups, action);
return state.setIn(['denomGroup', denomGroup.key, denomGroup.index, sum], parseFloat(action.value));
我是 React 和 redux 的新手。我有一个对象是一个子对象数组,其中包含数组
const initialState = {
sum: 0,
denomGroups: [
{
coins: [
{ name: 'Penny', namePlural: 'Pennies', label: '1¢', value: .01, sum: 0 },
{ name: 'Nickel', namePlural: 'Nickels', label: '5¢', value: .05, sum: 0 },
{ name: 'Dime', namePlural: 'Dimes', label: '10¢', value: .10, sum: 0 },
{ name: 'Quarter', namePlural: 'Quarters', label: '25¢', value: .25, sum: 0 }
]
},
{
bills: [
{ name: 'Dollar', namePlural: 'Dollars', label: '', value: 1, sum: 0 },
{ name: 'Five', namePlural: 'Fives', label: '', value: 5, sum: 0 },
{ name: 'Ten', namePlural: 'Tens', label: '', value: 10, sum: 0 },
{ name: 'Twenty', namePlural: 'Twentys', label: '', value: 20, sum: 0 },
{ name: 'Fifty', namePlural: 'Fiftys', label: '', value: 50, sum: 0 },
{ name: 'Hundred', namePlural: 'Hundreds', label: '0', value: 100, sum: 0 }
]
}
]
};
我有一个操作会传递一个值和面额名称
export function increaseSum(value, denom) {
return { type: types.ADD_TO_SUM, value: value, denom: denom }
}
在我的 reducer 内部,我写了一个助手 class 来识别这个面额在对象中的位置:
function findDenomination(denoms, action) {
let denomMap = {},
currentDenom = {};
for (let i = 0; denoms.length >= i + 1; i++) {
let denomGroup = denoms[Object.keys(denoms)[i]];
for (var key in denomGroup) {
if (!currentDenom.length) {
currentDenom = denomGroup[key].filter(x => x.name === action.denom);
if (currentDenom.length > 0) {
denomMap.group = i;
denomMap.key = key;
denomMap.index = denomGroup[key].findIndex(x => x.name === action.denom);
}
}
}
if (currentDenom.length > 0) {
break;
}
}
return denomMap;
}
并且在 reducer 本身中,我使用 Object.assign
来制作 denomGroups 的深度副本,以我认为保持不变的方式。
function countableItems(state = initialState, action) {
switch (action.type) {
case types.ADD_TO_SUM:
let denomMap = findDenomination(state.denomGroups, action);
state.denomGroups = Object.assign({}, state.denomGroups, state.denomGroups[denomMap.group][denomMap.key][denomMap.index].sum = parseFloat(action.value));
return state;
default:
return state;
}
}
有没有人清楚为什么这被标记为错误:A state mutation was detected inside a dispatch
你试图改变一个不可变的。因此错误。
不可变对象的全部要点在于,不可变对象在创建后永远不应该在其内部的任何地方发生变化。这就是为什么所有改变它的函数都会创建一个不可变的新实例。如果你试图改变一个不可变的深处的东西,那仍然是一个突变,因此很糟糕。
这确保您可以只检查对象本身是否相等,而不必进行深入检查,并确保数据完整性。
你应该做的只是改变它(如果你正在使用 immutables
库,你可以使用 setIn
),这将创建一个新的地图。您可以在 state
.
像这样:
case types.ADD_TO_SUM:
const denomMap = findDenomination(state.denomGroups, action);
return state.setIn(['denomGroup', denomGroup.key, denomGroup.index, sum], parseFloat(action.value));