dvdzkwsk / react-redux-starter-kit

Get started with React, Redux, and React-Router.
MIT License
10.28k stars 2.2k forks source link

Question - Injecting reducer into parent and child routes #1127

Open nicklee1990 opened 7 years ago

nicklee1990 commented 7 years ago

Summary of question Is there a way of injecting a reducer for a route and all it's child routes using injectReducer in the parent route definition?

Detailed Description I'm injecting a reducer for my index route (/projects) and it works fine. My child route /projects/:id also needs the reducer to be injected because the projects slice of the state tree contains data it needs (there is a key called projectsById which contains the details for each project). If I visit the child route after the index route it works fine because the reducer has been injected. However if I visit /projects/:id the route does not load because the reducer has not been injected, shown by the message Cannot read property 'projectsById' of undefined since state.projects is undefined. My temporary solution was to just inject the reducer in getChildRoutes but is there a better way of doing this? The copy/paste felt a bit dirty. My code which works at the moment:

  getIndexRoute (partialNextState, callback) {
    require.ensure([], function (require) {
      /*  Add the reducer to the store on key 'projects'  */
      const reducer = require('./modules/projects').default
      injectReducer(store, { key: 'projects', reducer })

      callback(null, {
        component: require('./containers/ProjectsViewContainer').default
      })
    }, 'projects')
  },

  getChildRoutes (partialNextState, callback) {
    require.ensure(['./containers/ProjectsViewContainer'], function (require) {
      // Don't want to repeat this
      const reducer = require('./modules/projects').default
      injectReducer(store, { key: 'projects', reducer })
      callback(null, [
        { path: ':id', component: require('./containers/ProjectOverviewContainer').default }
      ])
    })
  },

I'd like to remove the duplicate injection of the reducer but I'm not sure how to do this and keep it working. I saw similar issues #1049 and #797 but they are not quite the same. Perhaps I'm going about it the wrong way with getIndexRoute and should be using it in conjunction with getComponent somehow?

Awesome starter kit - really appreciate the hard work you guys put in

nicklee1990 commented 7 years ago

I think I managed to solve this by doing the following:

getComponent(location,cb) {
    require.ensure([], function (require) {
      /*  Add the reducer to the store on key 'projects'  */
      const reducer = require('./modules/projects').default
      injectReducer(store, { key: 'projects', reducer })

      cb(null, require('./containers/ProjectsLayout').default)
    }, 'projects')
  },

  getIndexRoute (partialNextState, callback) {
    require.ensure([], function (require) {
      callback(null, {
        component: require('./containers/ProjectsViewContainer').default
      })
    })
  },

  getChildRoutes (partialNextState, callback) {
    require.ensure(['./containers/ProjectsViewContainer'], function (require) {
      callback(null, [
        { path: ':id', component: require('./containers/ProjectOverviewContainer').default }
      ])
    })
  },

Where ProjectsLayout is just export default ProjectsLayout = ({ children }) => children. From what I can tell it works nicely but not sure if it's the "right" way

popaulina commented 7 years ago

This helped me a lot, thank you! 👍