mantrajs / mantra-core

Collection of Core APIs used in Mantra
MIT License
65 stars 36 forks source link

Basic support for modularity using react-router #5

Open chmanie opened 8 years ago

chmanie commented 8 years ago

I have a proposition on how mantra could support react-router (as discussed here) while maintaining modularity and not changing the mantra API at all.

We can use the "huge apps" pattern to do the route setup inside the mantra modules (routes.jsx as it is now).

The only thing we'd need to do is return the resulting route configuration here like this:

const routes = this._routeFns.map(routeFn => {
  const inject = comp => {
    return injectDeps(this.context, this.actions)(comp);
  };
  return routeFn(inject, this.context, this.actions);
});

this._routeFns = [];
this.__initialized = true;

return routes;

Or, if you plan to use to return something else from init() in the future:

return { routes };

Then one could use the react route objects to build up the react-router root like this:

const {routes} = app.init();

const rootRoute = {
  childRoutes: [ {
    path: '/',
    component: require('./components/App'),
    childRoutes: routes
  } ]
}

render((
  <Router
    history={browserHistory}
    routes={rootRoute}
  />
), document.getElementById('react-root'))

I think this would provide a great deal of flexibility and open the way for users who want to use react-router (or any other routing library for that matter) using a minimal invasive change.

I'd be happy to discuss this further and also eventually provide a PR for this. Let me know what you think.

khayong commented 8 years ago

There is a way where we can create the rootRoute object on Application Context and let each modules to assign their own route to the rootRoute, similar to FlowRouter.

configs/context.js

export default function () {
  return {
    Meteor,
    Collections,
    RootRoute: {
        childRoutes: []
    }
  }
}

modules/core/routes.jsx

export default function (injectDeps, {RootRoute}) {
  RootRoute.childRoutes.push({
    path: '/',
    component: require('./components/App'),
    childRoutes: []  
  }); 
}

render((
  <Router
    history={browserHistory}
    routes={RootRoute}
  />
), document.getElementById('react-root'))

for the other module to assign route, modules/calendar/routes.jsx

export default function (injectDeps, {RootRoute}) {
  RootRoute.childRoutes[0].childRoutes.push({
    path: 'calendar',
    getComponent(nextState, cb) {
      require.ensure([], (require) => {
        cb(null, require('./components/Calendar'))
      })
    }
  })
}