peter-mouland / react-lego

React-lego : incrementally add more cool stuff to your react app
http://react-lego.herokuapp.com/
MIT License
414 stars 36 forks source link

Fetching server-side data with async routes #39

Closed rkorrelboom closed 6 years ago

rkorrelboom commented 7 years ago

Hi Peter, thx for this awesome repo! I'm currently working on an implementation of server-side rendering and your guide at: https://github.com/peter-mouland/react-lego/wiki/Redux-Promise-Middleware helped a lot.

I've stumbled upon an issues using sync routes however and I'm curious if you have any insights on the following scenario:

  1. Render app component and fetch data on the server side using the needs construction
  2. App component generates routes based on fetched data
  3. Generated routes point to new component that also have data needs (which I would like to render on the server)

With your current solution only the data needs for the app component are resolved on the server because the data needs of sub components become available after the resolve of the initial data. At this point the server already returns because it doesn't know about new data needs.

What are your ideas about this?

peter-mouland commented 7 years ago

yeah, just a quick reply... only checking the root route with data needs have been enough for me so far as i've been able to keep my needs at the same level. I was aware of the current limitation in the solution and was going to try and solve once it was a problem for me... somehow it never has been.

having said that, the new react-router v4-beta.6 (not alpha as in my other examples) has a new way to match routes, and it basically exposes its own internal mechanism which is awesome. So i think, it should be possible with this:

this is a snippet of the new middle ware with the updated router. Hopefully i'm not being too optimistic in saying i see potential in this function being improved with the new matchPath function.

import matchPath from 'react-router-dom/matchPath';

async function getRouteData(routesArray, url, dispatch) {
  const needs = [];
  routesArray
    .filter((route) => route.component.needs)
    .forEach((route) => {
      const match = matchPath(url, route.path, { exact: true, strict: false });
      if (match) {
        route.component.needs.forEach((need) => {
          const result = need(match.params);
          needs.push(dispatch(result));
        });
      }
    });
  await Promise.all(needs);
}
rkorrelboom commented 7 years ago

Thx for the reply, i haven't looked into the new matchPath method but with your proposed solution I still see an issue when routes are generated from data that needs to be fetched first since the router wouldn't know about the new route. I'm currently working on a solution with a decorator to keep track of all open promises so I can keep resolving promises until there are none left. I'll post a snippet here once it's finished.

peter-mouland commented 7 years ago

that would be great, thanks 👍

dlebedynskyi commented 7 years ago

@rkorrelboom we ended up using same promise and hoc component based approach. Gist https://gist.github.com/dlebedynskyi/575cc138c57af6b47f7c3f917b1f57f4

rkorrelboom commented 7 years ago

@dlebedynskyi ah thx, looks like a pretty clean solution. I came up with the following approach: https://gist.github.com/rkorrelboom/fe64b2df4fe018590c6c2f0055856da1 curious what you guys think. (Async routes are missing in the example but it just works)

dlebedynskyi commented 7 years ago

@rkorrelboom I'd avoid creating default instance of Resolver https://gist.github.com/rkorrelboom/fe64b2df4fe018590c6c2f0055856da1#file-resolver-service-js-L32. on server this will be create on first module load and will stay active. This mean that on every render at https://gist.github.com/rkorrelboom/fe64b2df4fe018590c6c2f0055856da1#file-render-app-js-L16 you are going to use same exact promises array instance. Could lead to problems with array growing too big or having promises that are hanging.

rkorrelboom commented 7 years ago

@dlebedynskyi thx for the feedback, i'll look into that

peter-mouland commented 6 years ago

update: now looking forward to suspense!! 👀