markdalgleish/redial

Lazy routes + split reducers?

jaredpalmer opened this issue · 3 comments

I'm using @gaearon 's approach to splitting out reducers with @ryanflorence 's lazy routes. Is it still possible to use redial? If so, how would you modify the fetching/trigger logic?

// routes/index.js
// Root Route
import PostList from './PostList';
import App from './App';

export default function createRoutes(store) {
  const root = {
    path: '/',
    component: App,
    getChildRoutes(location, cb) {
      require.ensure([], (require) => {
        cb(null, [
          require('./Editor').default,
          require('./Post').default(store),
        ]);
      });
    },

    indexRoute: {
      component: PostList,
    },
  };

  return root;
}
// routes/Post/index.js
// Lazy Route
import { injectAsyncReducer } from '../../store';

export default function createRoutes(store) {
  return {
    path: 'post/:slug',
    getComponents(location, cb) {
      require.ensure([
          './containers/PostPage',
          './reducer',
        ], (require) => {
          let PostPage = require('./containers/PostPage').default;
          let postReducer = require('./reducer').default;
          injectAsyncReducer(store, 'currentPost', postReducer);
          cb(null, PostPage);
        });
    },
  };
}
// server.js
const redial = (path) => new Promise((resolve, reject) => {
  const store = configureStore();
  const routes = createRoutes(store);
  const { dispatch, getState } = store;
  const history = useQueries(createMemoryHistory)();
  const location = history.createLocation(path);

  match({ routes, location }, (routerError, redirectLocation, renderProps) => {
    const components = renderProps.routes.map(route => route.component);
    const locals = {
      path: renderProps.location.pathname,
      query: renderProps.location.query,
      params: renderProps.params,
      dispatch,
    };
    trigger('fetch', components, locals)
      .then(() => {
        const data = getState();
        const html = renderToString(
          <Provider store={store}>
            <RoutingContext {...renderProps} />
          </Provider>
        );
        resolve({ data, html});
      })
      .catch(e => reject(e));
  });
});

This is the error in the console:

[Error: Cannot automatically buffer without a document]

Fixed.

What was the fix?

Stopped using ac2bec9 solution and embraced loading states as better UX. Full example: https://github.com/jaredpalmer/react-production-starter