Reputation: 2150
I'm trying to wrap my head around how this reducer works so I can add a REMOVE_ITEM to my action handlers. My current try gives a state.filter is not a function error.
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[GET_POSTS]: (state, action) => ({ ...state, ...action.payload}),
[PICK_ITEM]: (state, action) => ({ ...state, ...action.payload}),
[REMOVE_ITEM]: (state, action) => ({...state.filter(item => item !== action.payload)}) // <-- NOT WORKING
}
// ------------------------------------
// Reducer
// ------------------------------------
const initialState = []
export default function contentReducer (state = initialState, action) {
const handler = ACTION_HANDLERS[action.type]
return handler ? handler(state, action) : state
}
I'm not quite sure about what's done with the spread and the destructure there. If I understand correctly the spread gives us a copied version of the state so we're not mutating it, but how is the following: handler(state, action)
creates our new state?
Upvotes: 2
Views: 869
Reputation: 67296
Each action, [GET_POSTS]
for example, is spreading state
and the action.payload
and returning the resulting value;
Yes, the {...state
bit spreads all the properties of state
into a new object.
This syntax is also like Object.assign
or _.merge
in that parameters to the right merge with the existing parameters to the left (over-writing if they are the same property.
Maybe if we produce a manual expansion this will make more sense.
With these:
const state = { a: 1, b: 2, c: 3 };
const action = { payload: { c: 4 }};
So this:
{ ...state, ...action.payload}
expands to:
{ ...{ a: 1, b: 2, c: 3 }, ...{ c: 4 }}
and from the left spreads first to:
{ a: 1, b: 2, c: 3, ...{ c: 4 }}
and then c
is overwritten making:
{ a: 1, b: 2, c: 4 }
Hope that helps.
Upvotes: 5