Redux updating nested data [Immutable Update Patterns]

Viewed 100

Can anyone help with this update pattern. I am not using any libraries like immer.

I have to update a nested object and the data looks like dis

Sample data

    { 
      isFetching: false
      data:{
            nba : {
                    stack :{
                            1:[]
                           }
                  }
           }
    }

My Reducer

 {
        ...state,
        isFetching: false,
        data: {
          ...state.data,
          [action.payload.team]: {
            ...state[action.payload.team],
            [action.payload.framework]: {
              ...state[action.payload.framework],
              [action.payload.build]: action.payload.resp
            }
          }
        }
 };

I am able to update until second level but unable to update third child. can anyone throw a light on where i am missing it.

I put a demo on codesandbox. https://codesandbox.io/s/todos-0ygrs

Click on collapse and inner collapse items. I am logging the changes for the state in the console below. As you can see at last level, build numbers are getting replaced with the new one's.

Current Behaviour After you expand nba and all the three childs

  {
    nba: {
           stack:{
                  3:[]
          }
  }

Expected Behaviour: After you expand stack and all the three childs

 {
    nba: {
           stack:{
                   1:[],
                   2:[],
                   3:[]
               }
         }
   }
2 Answers

You probably have to use a get helper because you may try to set a part of state that doesn't exist yet.

With the get helper you can set the state like this:

const { team, framework, build, resp } = action.payload;
const newState = {
  ...state,
  isFetching: false,
  data: {
    ...get(state, ['data']),
    [team]: {
      ...get(state, ['data', team]),
      [framework]: {
        ...get(state, ['data', team, framework]),
        [build]: resp,
      },
    },
  },
};

Somehow i figured out my mistake, Hope it helps someone in future

Initial state should not be null, it should be empty object and update pattern should be in this manner

 {
    ...state,
    isFetching: false,
    data: {
      ...state.data,
      [action.payload.team]: {
        ...state.data[action.payload.team],
        [action.payload.framework]: {
          ...state.data[action.payload.team][action.payload.framework],
          [action.payload.build]: action.payload.resp
        }
      }
    }
  };

if it fails, then try this way

let teamTemp = { ...state.data[action.payload.team]}

     {
        ...state,
        isFetching: false,
        data: {
          ...state.data,
          [action.payload.team]: {
            ...teamTemp ,
            [action.payload.framework]: {
              ...teamTemp[action.payload.framework],
              [action.payload.build]: action.payload.resp
            }
          }
        }
      };

I have forked my codesandbox and updated latest code.

Related