更新嵌套的不可变状态 (redux)



我希望将新的项目对象添加到化简器中的类别中。化简器接收类别索引和新项对象。

有谁知道使用此数据结构不变地更新状态的最佳方法:

const initialState = {    
categories: [
{
id: 1,
name: "vegetables",
items: [
{name: "potatoes", id: Math.floor(Math.random() * 99999)},
{name: "carrots", id: Math.floor(Math.random() * 99999)}
] 
},
{
id: 2,
name: "dairy",
items: [
{name: "milk", id: Math.floor(Math.random() * 99999)},
{name: "cheese", id: Math.floor(Math.random() * 99999)}
] 
},
{
id: 3,
name: "meat",
items: [
{name: "chicken", id: Math.floor(Math.random() * 99999)}
] 
}
]
}

还是最好使用外部包,例如不可变.js?

关于堆栈溢出还有许多其他类似的问题,但没有一个具有相同的结构。

更新

减速器的其余部分如下所示:

const shoppingItemsReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_SHOPPING_ITEM:
const categories = [...state.categories];

categories[action.selectedCategoryIndex].items.push(action.newItemObj);
return {
...state,
categories
}
default:
return state
}
}

使用push工作正常,但它正在改变状态

您可以在不使用 push 的情况下执行以下操作

const initialState = {    
categories: [
{
id: 1,
name: "vegetables",
items: [
{name: "potatoes", id: Math.floor(Math.random() * 99999)},
{name: "carrots", id: Math.floor(Math.random() * 99999)}
] 
},
{
id: 2,
name: "dairy",
items: [
{name: "milk", id: Math.floor(Math.random() * 99999)},
{name: "cheese", id: Math.floor(Math.random() * 99999)}
] 
},
{
id: 3,
name: "meat",
items: [
{name: "chicken", id: Math.floor(Math.random() * 99999)}
] 
}
]
}
const categoryId = 2; // categoy want to update
cosnt newItem = {name: "Butter", id: Math.floor(Math.random() * 99999)}
const newState = {
...initialState, // or state
categories: initialState.categories.map(category => {
if(category.id === categoryId) {
return {
...category,
items: [
...category.items,
newItem
]
}
}
return category;
)
}

包含基元类型的变量将始终指向实际值。 因此,如果将其传递给另一个变量,则另一个变量将获得该值的新副本。

但是,对象和数组始终通过引用传递。 因此,如果要将对象或数组传递给另一个变量,它们都将引用相同的原始对象。 如果要修改引用原始变量中的任何一个,它也会修改原始对象/数组。

要避免这种情况,您必须创建数组的新副本。你可以在普通的javascript中做到这一点,如下所示:

const initialState = [
{
id: 1,
name: "category 1",
items: [
{name: "item 1", id: 1},
{name: "item 2", id: 2}
] 
},
{
id: 2,
name: "category 2",
items: [
{name: "item 3", id: 3},
{name: "item 4", id: 4}
] 
},
{
id: 3,
name: "category 3",
items: [
{name: "item 5", id: 5},
{name: "item 6", id: 6}
] 
}
]

const newState = [...initialState, newDataObject]

newState 是一个新创建的数组,其中包含initialState的副本,newDataObject推送到newState数组的最后一个索引。

编辑:我看到你用你的redux化简器更新了你的问题。 您当前返回的对象引用了初始状态:

return {
...state,
categories
}

相反,它应该返回一个新对象,并将分类推到它上面。 您可以使用 es6 的Object.assign()合并两个对象,它将返回一个包含这两个对象的全新对象。

将您的退货声明更改为:

return Object.assign({}, state, categories)

相关内容

  • 没有找到相关文章

最新更新