我的Redux数据存储中具有以下结构:
{
filterData: {
22421: {
filterId: 22421,
selectedFilters: [
{
filterName: 'gender',
text: 'Male',
value: 'male'
},
{
filterName: 'gender',
text: 'female',
value: 'female'
}
]
}
22422: {
filterId: 22422,
selectedFilters: [
{
filterName: 'colour',
text: 'Blue',
value: 'blue'
},
{
filterName: 'animal',
text: 'sheep',
value: 'Sheep'
}
]
}
有人可以指出我要使用正确的方法来更新selectedFilters数组而不直接改变状态吗?即如何为给定的filterId添加/删除selectedFilters数组中的元素?
答案 0 :(得分:2)
通常通过使用非变异(即返回一个新对象,而不是修改现有对象)操作符和函数来完成此操作:
...
)用于对象和数组(用于添加和编辑),您必须在通向最终水平的每个级别上进行此操作-进行更改。对于您的情况,如果要更改其中一个对象的selectedFilters
,则必须执行以下操作:
// Assuming you're inside a reducer function.
case SOME_ACTION:
// Returning the new state object, since there's a change inside.
return {
// Prepend old values of the state to this new object.
...state,
// Create a new value for the filters property,
// since—again—there's a change inside.
filterData: {
// Once again, copy all the old values of the filters property…
...state.filters,
// … and create a new value for the filter you want to edit.
// This one will be about removal of the filter.
22421: {
// Here we go again with the copy of the previous value.
...state.filters[22421],
// Since it's an array and we want to remove a value,
// the filter method will work the best.
selectedFilters:
state.filters[22421].selectedFilters.filter(
// Let's say you're removing a filter by its name and the name
// that needs to be removed comes from the action's payload.
selectedFilter => selectedFilter.name !== action.payload
)
},
// This one could be about addition of a new filter.
22422: {
...state.filters[22422],
// Spread works best for additions. It returns a new array
// with the old values being placed inside a new one.
selectedFilters: [
// You know the drill.
...state.filters[22422].selectedFilters,
// Add this new filter object to the new array of filters.
{
filterName: 'SomeName',
text: 'some text',
value: action.value // Let's say the value comes form the action.
}
]
},
}
}
此常数“复制旧值”是必需的,以确保保留嵌套对象中的值,因为散布运算符以浅方式复制属性。
const someObj = {a: {b: 10}, c: 20}
const modifiedObj = {...someObj, a: {d: 30}}
// modifiedObj is {a: {d: 30}, c: 20}, instead of
// {a: {b: 10, d: 30}, c: 20} if spread created a deep copy.
您可以看到,这有点平凡。解决该问题的一种方法是创建某种嵌套的reducers函数,这些函数将在该州的不同树上工作。但是,有时最好不要重新发明工具,而应使用已经解决这些问题的工具。像Immutable.js。
答案 1 :(得分:1)
如果您想使用专用的库来管理不可变状态(如另一个答案中所建议的那样),请查看Immer。
我发现该库比Immutable.js更简单(而且包的大小也会更小)