flexdinesh / react-redux-boilerplate

A minimal React-Redux boilerplate with all the best practices
MIT License
782 stars 274 forks source link

Reducer initialState is never set if it's dynamically injected #12

Closed ethax-ross closed 6 years ago

ethax-ross commented 6 years ago

If I don't include a reducer in reducers.js:

export default function createReducer(injectedReducers) {
  return combineReducers({
    route: routeReducer,
    global: globalReducer,
    ...injectedReducers,
  });
}

And instead just inject it like so:

const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'modules', reducer });
const withSaga = injectSaga({ key: 'modules', saga });

export default compose(withReducer, withSaga, withConnect)(App);

Then reducer never seems to set it's initialState - I assume because they don't seem to receive the @@INIT action that causes it to hit the default in it's case statement:

function myReducer(state = initialState, action) {
  switch (action.type) {
    case DO_SOMETHING:
      ...
    default:
      return state; <- never happens
  }
}

It looks like this is because it gets injected at componentWillMount, which is after @@INIT... how do I get the initialState set so that it can be referenced at componentDidMount?

ethax-ross commented 6 years ago

I found the/a solution - we should just export the initialState from the reducer and use it as the default value in the selector as they do here:

https://github.com/react-boilerplate/react-boilerplate/blob/98f5c0e5bc54a5540466515e38dea9e9cb752019/app/containers/HomePage/selectors.js#L8

In here:

https://github.com/flexdinesh/react-redux-boilerplate/blob/master/app/containers/HomePage/selectors.js#L7

flexdinesh commented 6 years ago

@ross-freeagent It's an interesting find. I am away from my dev machine for three weeks now and I won't have access for two more weeks I guess. If you could create a PR, I'll be able to merge it though.

ruslansavenok commented 6 years ago

Selector solution will not update redux state, therefore redux devtools will not show that reducer initial state attached.

You could do store.dispatch({ type: '@@REDUCER_INJECTED' }); (basically dispatching any action) after store.replaceReducer, this will set initial state of the reducer to store state.

flexdinesh commented 6 years ago

Thanks @ross-freeagent, @ruslansavenok and @piotr-roslaniec. The PR with the proposed solution is now merged.