Search code examples
reactjsreduxreact-reduximmutable.jsnested-object

Update deeply nested state object in redux without spread operator


I've been breaking my head for a week or something with this !!

My redux state looks similar to this

{
  data: {
      chunk_1: {
        deep: {
         message: "Hi"
        }
      },
      chunk_2: {
        something: {
         something_else: {...}
        }
      },
     ... + more
  },
  meta: {
   session: {...},
   loading: true (or false)
  }
}

I have an array of keys like ["path", "to", "node"] and some data which the last node of my deeply nested state object should be replaced with, in my action.payload.

Clearly I can't use spread operator as shown in the docs (coz, my keys array is dynamic and can change both in values and in length). I already tried using Immutable.js but in vain.. Here's my code

// Importing modules ------ 
import {fromJS} from "immutable";

// Initializing State --------- 
const InitialState = fromJS({ // Immutable.Map() doesn't work either
    data: { ... },
    meta: {
        session: {
            user: {},
        },
        loading: false,
        error: "",
    },
});

// Redux Root Reducer ------------
function StoreReducer(state = InitialState, action) {
  
  switch (action.type) {
    case START_LOADING: 
    return state.setIn(["meta"], (x) => {
                return { ...x, loading: true };
    });

    case ADD_DATA: {
      const keys = action.payload.keys; // This is a valid array of keys
      return state.updateIn(keys, () => action.payload); // setIn doesn't work either
    }
  
}

Error I get..

Uncaught TypeError: state.setIn (or state.updateIn) is not a function
    at StoreReducer (reducers.js:33:1)
    at k (<anonymous>:2235:16)
    at D (<anonymous>:2251:13)
    at <anonymous>:2464:20
    at Object.dispatch (redux.js:288:1)
    at e (<anonymous>:2494:20)
    at serializableStateInvariantMiddleware.ts:172:1
    at index.js:20:1
    at Object.dispatch (immutableStateInvariantMiddleware.ts:258:1)
    at Object.dispatch (<anonymous>:3665:80)

What I want ?

The correct way to update my redux state (deeply nested object) with a array containing the keys.


Solution

  • Please note that you are using an incredibly outdated style of Redux. We are not recommending hand-written switch..case reducers or the immutable library since 2019. Instead, you should be using the official Redux Toolkit with createSlice, which allows you to just write mutating logic in your case reducers (and thus also just using any helper library if you want to use one).

    Please read Why Redux Toolkit is how to use Redux today.