0

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.

2 Answers 2

2

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,
    ]
Sign up to request clarification or add additional context in comments.

Comments

0

This can be done with Immer

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.