Как правило, это делается с использованием не изменяющих (т.е. возвращающих новый объект, а не изменяющих существующий) операторов и функций:
Вы должны делать это на каждом уровне, ведущем к последнему - где происходят ваши изменения.В вашем случае, если вы хотите изменить 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.
Как видите, это немного обыденно.Одним из решений этой проблемы было бы создание неких вложенных функций-редукторов, которые будут работать на отдельных деревьях состояния.Тем не менее, иногда лучше не заново изобретать устройство и использовать уже имеющиеся инструменты, которые были созданы для решения подобных проблем.Как Immutable.js .