Reputation: 1494
I want to know how I can return an immutable object from a function (a reducer in react but that's not really important) to combine an array of objects (state
) with another object payload
that has a nested object subResults
. I basically want to return state with the 2 records below but the first record would have a sub property called subNodes
because state.results[0].name === payload[0].name
state = {results:[
{name:'name 1', description: 'I am a description'},
{name:'name 2', description: 'I am a second description'}
]};
payload = {results: [ {name:'name 1', subResults:{type:'whatever'} }]};
It kinda works if I call:
{
...state,
results: {
...state.results,
...payload.results[0]
}
}
The problem here is that I lose the 'description' property because the payload object doesn't have 'description' and overrides the state object. I want to keep the state object as it is and only append the 'subResults'. I'm also hard coding the index[0] while I would like to use the name property to override like I mentioned above.
Anyone have any ideas?
Upvotes: 1
Views: 271
Reputation: 11
Result is an array of object, so you would have to iterate over the values, also if you want to merge the value if the name are the same, a couple of array functions could be helpful
const state = {
results: [
{ name: 'name 1', description: 'I am a description' },
{ name: 'name 2', description: 'I am a second description' },
],
}
const payload = {
results: [
{ name: 'name 1', subResults: { type: 'whatever' } },
{ name: 'name 3', description: 'third one' },
],
}
function merge(state, payload) {
return {
...state,
...payload,
results: payload.results.reduce((newResults, newItem) => {
// if item doesn't exist on the state, we add it
if (!newResults.some(item => newItem.name === item.name)) {
return [...newResults, newItem]
}
// otherwise, we merge it with the payload item information
return newResults.map(item => {
if (item.name === newItem.name) {
return {
...item,
...newItem,
}
}
return item
})
}, state.results),
}
}
const newState = merge(state, payload)
console.log(newState)
Upvotes: 1