S. Schenk S. Schenk - 3 months ago 8
Javascript Question

Understand spread and destructure use in the following reducer

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?

Answer

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.

Comments