-
Notifications
You must be signed in to change notification settings - Fork 787
Pre-fetch data recursively before a route transition #153
Comments
@amannn this is really interesting. I'm not sure the best way to go about doing this. A variation on |
I got a non-recursive version working with a react-router onEnter hook. The gist is: function fetchRouteData(nextState, replace, cb) {
const props = {params: nextState.params, location: nextState.location};
const result = this.component.fetchData(props, {client});
if (result instanceof Promise) result.then(() => { cb(); });
else cb();
} That works pretty well so far. One thing that might could be improved though is that I have to put a check like the following in the render function: render() {
if (this.props.data.loading) return null;
} As far as I understand, while server rendering the Is that correct? If so, does that behaviour really make sense? My usecase is somewhat special but what if that component would render another graphql-wrapped component that's only rendered when the parent component renders with its fetched data? Wouldn't it make sense to wait for the |
@amannn the server will go to the deepest part of the tree it can. Then fetch the data, then pick up there to keep going. render() {
if (this.props.data.loading) return null;
} If you do the above, it will stop there, then pick up rendering down the tree after it gets data |
Oh, really? That's pretty cool actually. I just tried it out. If a put Really cool anyway! |
I think pre-caching data based on traversing the view hierarchy is a Really Cool Idea. @amannn if you get this working, I'd love to learn more about how we can make it easier, because that would be a seriously killer feature. |
I did an experiment with running In a very simple case where you have a const context = {client};
getDataFromTree(component, context).then(() => {
console.log('all data down the tree pre-fetched');
}); That's pretty simple if the apollo client is the only thing that needs to be present on the context. However in my scenario it's a bit more difficult. I also need So the options for my use case are
So I think the bottom line for my use case is that it's possible, but pretty hackish. However this is more related to the react-router API (or my weird use case 😀) – I think from the Apollo side there's not much to improve. It's also worth noting that the maintainers of react-router think it's bad practice to do data fetching in The only thing that could be improved on the Apollo side, is that an app that imports |
It would be really cool to get a blog post going about this! |
I am struggling with server-side rendering when using an existing redux store. Here is my route handler: const handleRoute = (res, routes, renderProps) => {
const client = new ApolloClient({
ssrMode: true,
networkInterface: createNetworkInterface('http://127.0.0.1:8003/')
});
const store = createStore(undefined, client);
const app = <ApolloProvider client={client} store={store} immutable={true}>
<RouterContext {...renderProps} />
</ApolloProvider>;
const test = {client};
getDataFromTree(app, test)
.then((context) => {
console.log('test.client.store.getState().apollo', test.client.store.getState().apollo);
console.log("context.store.getState().get('apollo')", context.store.getState().get('apollo'));
console.log("store.getState().get('apollo')", store.getState().get('apollo'));
});
}; Here is the output:
What am I missing? |
Can you open a separate issue on react-Apollo about this please? |
Thanks for this thread @amannn, and thanks for all your work @stubailo, Apollo is 💯 I've recently been investigating the idea of prefetching views as well and have a tentative solution that relies on react-router's renderProps passed to a router middleware: apollo-prefetch. It's rough and untested in production, still trying to suss out whether it's a true solution to this problem, but it works well with my current local setup and I hope to continue development to a production level. Not sure if this helps, just hoping to get some experienced eyes on it 😁 would love any feedback or questions you have. |
I think that's a good start! Perhaps we could use some of the machinery from server side rendering to make this happen? It already crawls the component tree for data to fetch: https://github.com/apollostack/react-apollo/blob/6743af261f9cc8ebb840fa163f6e1e6711bc5f3f/src/server.ts#L97 Also, can you open a new issue about it? This one is somewhat old. |
Congratulations on the release of v0.4! Looks really good to me!
I once commented on an issue of react-router-apollo (which is now a bit outdated) with a description of a scenario that I'd like to implement using react-apollo.
It's actually very similar to when you're on https://github.com/apollostack/react-apollo and click on the Issues tab (and back to Code if you like). The loading indicator tells you that the app is loading and once all data for the target page is loaded, the transition will happen. If the loading fails, I want the user stay on the same page so she can try again by clicking on the same link again.
I'm pretty sure this is already possible with the current state of Apollo, however it get's a bit more challenging when there are nested graphql containers within a route handler that will only render when the parent container got its data and renders.
I've noticed that there's now the
getDataFromTree
function that can be used to pre-fetch data for a given tree. As far as I understand, this works recursively also for nested containers, right? My goal is that there can be a route transition to a complex page with lots of nested graphql containers without showing a loading spinner once on the target page.Could this be used for my scenario? I've seen that the method is imported from
react-apollo/server
, so I wasn't sure if it's a good idea to also do this on the client side? Maybe there are other things to consider as well. It seems likegetDataFromTree
produces a new store state, whereas in my case I'd like it to act on an existing store.Thanks for your help!
The text was updated successfully, but these errors were encountered: