Sankalp Singha
Sankalp Singha

Reputation: 4546

Merging two objects with inner array properties without mutating the state in react

I have got a state object like so :

{
    news: {
        news: [
            {
                id: 1,
                name: 'test1'
            },
            {
                id: 2,
                name: 'test2'
            },
            {
                id: 3,
                name: 'test3'
            }
        ]
    }
    ]
}

Now, I am making an Ajax request and getting my response like so:

[
    {
        id: 4,
        name: 'test4'   
    },
    {
        id: 5,
        name: 'test5'   
    },
    {
        id: 6,
        name: 'test6'   
    }
]

I dont want to mutate the state, so in my Reducer, how do I merge the two values so that the final output is like so:

{
    news: {
        news: [
            {
                id: 1,
                name: 'test1'
            },
            {
                id: 2,
                name: 'test2'
            },
            {
                id: 3,
                name: 'test3'
            },
            {
                id: 4,
                name: 'test4'   
            },
            {
                id: 5,
                name: 'test5'   
            },
            {
                id: 6,
                name: 'test6'   
            }
        ]
    }
    ]
}

I tried something like this, however, it replaced the entire news object.

return { ...state, news: action.payload }

Where action.payload has the values that I am getting in my response. I know I might be missing something simple and obvious in this.

Upvotes: 1

Views: 302

Answers (2)

ehutchllew
ehutchllew

Reputation: 958

This is a helper function that will do a deep clone for you regardless of the structure:

function deepClone(obj){
    return Object.keys(obj).reduce((objClone, key) => {
        let newValue;

        if(Array.isArray(obj[key]){
            newValue = obj[key].map(item => deepClone(item));
        }
        else if(obj[key] !== null && typeof obj[key] = 'object'){
            newValue = deepclone(obj[key]);
        }
        else{
            newvalue = obj[key];
        }

        return {...copyObj, [key]: newvalue};
    }, {});
}

Upvotes: 0

adiga
adiga

Reputation: 35222

Assuming action.payload is the news array returned by the ajax:

return { ...state, news: { news: [...state.news.news, ...action.payload] } }

Upvotes: 4

Related Questions