簡體   English   中英

更新嵌套的不可變狀態(redux)

[英]Updating nested immutable state (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)}
            ] 
        }
    ]
}

還是最好使用外部軟件包,例如immutable.js?

關於stackoverflow還有很多其他類似的問題,但是沒有一個具有相同的結構。

更新

減速器的其余部分看起來像:

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可以正常工作,但是會改變狀態

您可以在不使用推送的情況下執行以下操作

 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 reducer更新了你的問題。 您當前正在返回引用初始狀態的對象:

    return {
        ...state,
        categories
    }

相反,它應該返回一個新對象,並將其添加到目錄中。 您可以使用es6的Object.assign()合並兩個對象,它將返回一個包含兩個對象的全新對象。

將您的退貨單更改為:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM