Reputation: 2922
I have an initial state like this:
export const INITIAL_STATE = Immutable({
payload: []
})
When I dispatch the request action, it returns an array of objects, something like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'}
]
So, when I try to refresh the state, I merge the existing payload with the new one I get from my server:
export const success = (state, { payload }) => {
const newPayload = state.payload.concat(payload)
return state.merge({ payload: newPayload })
}
This makes my new state end up something like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'}
]
So, that part works, but, if I call again my request action, the state is getting populated with duplicated data, like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'},
{id: 1, name: 'userA'}, // <== duplicated data
{id: 2, name: 'userB'}, // <== duplicated data
{id: 3, name: 'userC'} // <== duplicated data
]
What I need is that if I call the request action, and the same data is returned from the server - in this case ids 1, 2 and 3 - then for state.merge to just leave the payload as it is or update them with new values if that's the case, so if user with id 2 updated his name in the server to newUserB then my new state would be like:
[
{id: 1, name: 'userA'},
{id: 2, name: 'newUserB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'}
]
instead of this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'},
{id: 1, name: 'userA'},
{id: 2, name: 'newUserB'},
{id: 3, name: 'userC'}
]
I have tried using state.merge({ payload: newPayload }, {deep: true})
but it's not working the way I expect, I also tried state.merge({ payload })
and the same.
Anyone knows how to accomplish this?
Upvotes: 4
Views: 4559
Reputation: 7180
Firstly merge the two arrays and then filter only unique items.
export const success = (state, { payload }) => {
const newArr = state.payload.concat(payload)
const idPositions = newArr.map(el => el.id)
const newPayload = newArr.filter((item, pos, arr) => {
return idPositions.indexOf(item.id) == pos;
})
return state.merge({ payload: newPayload })
}
Upvotes: 2