-
Notifications
You must be signed in to change notification settings - Fork 51
Implement data-fetching for server rendering #51
Comments
Something like this (in traverse.js)? Just tried it out and it seems to work.
|
Feels like this would be a good candidate to explore optional Rapscallion plugins/middleware. It's a very workflow specific thing to have to have in the main library. |
It is non-standard but there is definitely general demand for a feature like this. For example, the apollo client currently traverses a react tree before every render to resolve data dependencies (if that could be done during SSR it would introduce a great performance boost to many graphql apps). Other libraries have introduced functionality to solve the same issue. I think the approach that is really emerging as a convention within the community is to extend the component contract with @stubailo @jbaxleyiii might be able to offer some thoughts on this from the perspective of a library author. |
Thanks for pointing me to |
Oh don't get me wrong - it's a cool feature. Was just questioning if it should be a core feature. Feels very... extend-y. That's usually the domain of plugins, especially when it's not core to the features of a project. Of course that depends on project goals/architecture choices. |
@abritinthebay I'm open to exposing a generic plugin interface. My concern with that, however, is that it will be difficult to implement in a way that does not hurt performance. If you have thoughts on how to accomplish that, I'd be eager to hear them. In any event, the implementation will be as non-specific as we can manage without hurting perf. |
True, though I'd argue the same is probably in this case - it's all going to have hot-path impact no matter what. |
Yeah I think our approach is something similar to getInitialProps, but you can put it anywhere in the tree. I think it's definitely desirable that SSR is possible without requiring a static mapping of URL -> data fetch. |
@divmain @abritinthebay How about allowing a visitor function (something similar to https://github.com/ctrlplusb/react-tree-walker) to be attached to the renderer? render(<App />)
.attachVisitor(function visitor(element, instance, context) {
if (instance.getInitialProps) {
// returning a promise pauses traversal until promise resolves
return instance.getInitialProps().then(initialProps => {
instance.props = initialProps
})
}
})
.toPromise() That would provide a flexible generic interface, and common visitors such as cc. @ctrlplusb |
That seems a reasonable approach. I'll look into whether this approach adds any performance overhead. It should be possible to add this without impacting perf for those not using the feature... |
Hey all! My promise-based API is now officially released for I also released I am using this with great success within Sorry, that is a mess of links. 😀 |
Maybe my own attempt at solving this issue can be helpful here: Instead of hacking the React lifecycle functions, I use a specially marked higher-order component, which is detected during the recursive traversal of the tree. I think separating the preparation step from the rendering step is usually a good idea, and I could implement a stream-friendly API so that it works nice with |
Also, https://github.com/elierotenberg/react-traverse performs deep components output rewriting, using higher order magic. Sorry for the plugs, but I think this can shed a light on various approaches to tackle this problem. |
Nice! Thanks for sharing @elierotenberg.
This means traversing the React tree twice. In my experiments that was always slower than resolving async work while rendering. If we go ahead with a plugin approach (e.g. #51 (comment)) then you could write a plugin that conforms to your projects' APIs. |
Will fiber land and change everything? |
To be clear “asynchronous” Fiber features are not related to server side rendering. They’re related to client-side updates. The new server side renderer is not even using Fiber, and is written as standalone renderer with a simple |
@gaearon Thanks for the clarification! Is a server side renderer that is capable of doing async work during rendering likely to fall on the React roadmap in the future? |
It might. @sebmarkbage was looking into this. |
This is more of a question, but would it be possible to implement something like this into Rapscallion? https://github.com/rexhome7326/sync-will-mount
Tested it and it works, lets you await a promise in ComponentWillMount() before continuing render.
With React Router 4's new API data fetching is a little more cumbersome, so a lot of people are looking for simpler solutions to server side data fetching.
The text was updated successfully, but these errors were encountered: