2

react-boilerplate has a utility injectReducer that is used to allow a reducer to be asynchronously attached to the store, and in the reducers.js file for the entire application, createReducer spreads out these injectedReducers into the state so that you have a state shape as follows:

{
  route: routeReducer,
  language: languageProviderReducer,
  container1: container1Reducer,
  container2: container2Reducer,
  container3: container3Reducer,
}

I would like instead to spread out these container-specific reducers to a subkey of the global state like so:

{
  route: routeReducer,
  language: languageProviderReducer,
  ui: {
    container1: container1Reducer,
    container2: container2Reducer,
    container3: container3Reducer,
  }
}

I naively tried to modify the reducers.js method createReducer like so:

export default function createReducer(injectedReducers) {
  return combineReducers({
    route: routeReducer,
    language: languageProviderReducer,
    ui: (injectedReducers) ? combineReducers(injectedReducers) : ((state = {}) => state),
  });
}

or maybe:

export default function createReducer(injectedReducers) {
  return combineReducers({
    route: routeReducer,
    language: languageProviderReducer,
    ui: combineReducers(injectedReducers || {}),
  });
}

But now when I try to load any container, I get an error: TypeError: Cannot read property '_currentElement' of null.

What is the easiest path to achieve the kind of state shape I want using injected reducers and react-boilerplate?

tacos_tacos_tacos
  • 10,277
  • 11
  • 73
  • 126

1 Answers1

1

The key for me I believe was to only add the ui key when it was needed (when at least one injectedReducers was present).

/**
 * Creates the main reducer with the dynamically injected ones
 */
export default function createReducer(injectedReducers) {
  const reducersToCombine = {
    form: formReducer,
    language: languageProviderReducer,
    route: routeReducer,
  };

  if (injectedReducers && Object.keys(injectedReducers).length > 0) {
    reducersToCombine.ui = combineReducers(injectedReducers);
  }

  return combineReducers(reducersToCombine);
}
tacos_tacos_tacos
  • 10,277
  • 11
  • 73
  • 126
  • Did it and realized that if I attach same reducer to several keys like { `forms` : {`id1` : reducer, `id2`: reducer}} I also need in action since now I have two reducers that handle same action. Though they mutate separate part of state, without id in action both may mutate on one action specific to concrete id. – nikita Aug 15 '19 at 08:25