RedOster
RedOster

Reputation: 325

Redux - Adding element to array nested in an object inside an array

Can't figure out how to properly insert an element into an array, that's inside an object, that's inside an array. Here's an example of my default data for structure:

const defaultState = {
  myinbox: [
    {
      owner: 'John Lennon',
      owner_id: 1,
      read: true,
      messages: [
        {
          _id: 1,
          text: 'When will you be home?',
          createdAt: new Date(Date.UTC(2017, 10, 11, 11, 20, 0)),
          user: {
            _id: 1,
            name: 'John Lennon'
          }
        }
 ...

I want to add another message when an inbound message comes in. This is what the snippet from my reducer looks like:

const inboxReducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'ADD_INBOUND_MESSAGE':
      return {
        ...state,
        myinbox: [
          state.myinbox[action.payload.index]: {
            ...state.myinbox[action.payload.index],
            messages: [
              ...state.myinbox[action.payload.index].messages,
              action.payload.msg
            ]
          }
          ...state.myinbox,
        ]
      }
  default:
    return state
  }
}

The index of the parent "owner" is passed as the index inside the payload, and the new message is msg in the payload.

I can't figure out how to write this reducer without mutating the original state.

Upvotes: 0

Views: 1063

Answers (2)

Vyacheslav Sedykh
Vyacheslav Sedykh

Reputation: 1

This can be done with Immer

  const { index, msg } = action.payload;
  return produce(state, (draftState) => {
    draftState.myinbox[index].messages.push(msg);
  });

Upvotes: 0

Chris Dolphin
Chris Dolphin

Reputation: 1598

You're mutating the original state when you set myinbox using state.myinbox[action.payload.index]:.

Looks like you're trying to set the state for the index using computed property keys. The syntax for that would be:

    myinbox: [
      [action.payload.index]: {
        ...state.myinbox[action.payload.index],
        messages: [
          ...state.myinbox[action.payload.index].messages,
          action.payload.msg
        ]
      }
      ...state.myinbox,
    ]

Upvotes: 2

Related Questions