Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Isomorphic Redux with code splitting and lazy loaded reducers

Tags:

redux

I am building an isomorphic application with code splitting using react router and redux. I have gone about as far as I can, but I need some help to figure out the rest of my problem. I have a large application that requires code splitting for the front end. I have a reducer registry that enables me to register new reducers(lazy loaded), or replace existing reducers in my store. This works great, however because sections of my app are lazy loaded, my lazy loaded reducers are not present when I call combineReducers() on the client side, while they resolve perfectly on the server. This causes an unexpected keys error, and forces my store to ignore the offending key(s) in my initial state.

initialState (from server)

{ "cases": {...}, "user": {...} }

Client side redux expected initialState

This is based off of available reducers

{ "user": {...} }

Loaded Reducer

  • UserReducer

Lazy Loaded Reducer

  • CaseReducer

The error occurs when I call the following

const finalCreateStore = compose(
  applyMiddleware(promiseMiddleware)
)(createStore);
const rootReducer = combineReducers({...reducers})
const store = finalCreateStore(rootReducer, initialState);

Unexpected key "case" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "user". Unexpected keys will be ignored.

Everything works well on the server, but initializing the app on the client while momentarily missing a reducer until it is loaded is causing this error. Does anyone know how to get around this error, or tell redux to not validate the shape of the initial state? I need "cases" to be available to my lazy loaded reducer.

like image 726
Dahminator Avatar asked Dec 22 '15 01:12

Dahminator


1 Answers

It seems like you should opt not to use the built-in combineReducers, since you know the warning isn't applicable to your usage. From the Redux guide:

These two ways to write a combined reducer are completely equivalent:

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})

function reducer(state, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}

So you may as well go with the second option.

like image 97
acjay Avatar answered Nov 07 '22 13:11

acjay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!