2

QUESTION: What's the best way to push a new payload object, to a nested redux reducers state?

I would like to push a new item location to the current lists array within the reducers function, using the current state index values.

MY CURRENT REDUX ACTION:

export const addLocation = () => {
  return (dispatch) => {
    axios.post("/inventory/lists/addlocation", locationData).then((res) => {
        dispatch({
          type: ADD_POSTED_LOCATION,
          payload: {location: "test", count: 0, _id: "6a5e4f6ae51g6ea5r1ga6e1rf"},
        });
    });
  };
};

MY CURRENT REDUCER:

const initialState = {
  lists: [],
  currentIndex: {
    listIndex: null,
    itemIndex: null,
    locationIndex: null
  },
};

export default function(state = initialState, action) {
  switch (action.type) {
    case ADD_POSTED_LOCATION:
      const listIndex = state.currentIndex.listIndex;
      const itemIndex = state.currentIndex.listIndex;
      return {
        ...state,
        lists: state.lists[listIndex ].items[itemIndex].locations.push(action.payload)
      };
My current result is simple:

lists: [a number, excluding the list objects and values]

DESIRED RESULT:

Lists: [

    {
      _id: "L1",
      items: [{
          number: "n1",
          locations: [{
            location: "L1"
          }, {
            location: "L2"
          }]
        },
        {
          number: "n2",
          locations: [{
              location: "L1"
            }, {
              location: "L2"
            },
            {
              location: "L3"
            },
            {
              location: "L4"
            }, {
              location: "L5"
            }
          ]
        }
      ]

    ]

2 Answers 2

1

You should always shallow copy any part of state you are updating, including nested arrays and objects.

export default function (state = initialState, action) {
  switch (action.type) {
    case ADD_POSTED_LOCATION:
      const listIndex = state.currentIndex.listIndex;
      const itemIndex = state.currentIndex.listIndex;
      return {
        ...state,
        lists: state.lists.map((list, lIndex) =>
          lIndex === listIndex
            ? {
                ...list,
                items: list.items.map((item, iIndex) =>
                  iIndex === itemIndex
                    ? {
                        ...item,
                        locaitons: [...item.locations, action.payload]
                      }
                    : item
                )
              }
            : list
        )
      };
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Hey Drew, I did some more testing with this. The code only adds the object to the first item of the first list. The issue is that I have multiple lists, with multiple items per list, with multiple locations per item.
@pc.dependency Do you have a working example of this I could also test? Maybe in a running codesandbox? I could see this happening if both state.currentIndex.listIndex and state.currentIndex.listIndex are 0.
my apologies, the issue was just grammar, thanks! I will upvote when i get to lvl 15!
@pc.dependency Great! And no worries, I wasn't able to actually test that code so TBH it was entirely possible there was an issue with it.
0

Fixed a few simple errors, and grammar. This is the Solution, Thanks Drew!

I learned that you must make shallow copies of your nested object structure using the spread operator (...). Also, utilizing the optional .map() index parameter allows you to use the mapped array's index values to compare with other index variables. Very Nice!

export default function(state = initialState, action) {
  switch (action.type) {
    case ADD_POSTED_LOCATION:
      return {
        ...state,
        lists: state.lists.map((list, lIndex) =>
          lIndex === state.currentIndex.listIndex ?
          {
            ...list,
            items: list.items.map((item, iIndex) =>
              iIndex === state.currentIndex.itemIndex ?
              {
                ...item,
                locations: [...item.locations, action.payload]
              } :
              item
            )
          } :
          list
        )
      };
  }
}

Comments

Your Answer

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