-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SSR (for Next static HTML export) with hooks #132
Comments
Update your import React from "react";
import initApollo from "./init-apollo";
import Head from "next/head";
import { getDataFromTree } from "react-apollo";
+ import { getMarkupFromTree } from "react-apollo-hooks";
+ import { renderToString } from "react-dom/server";
export default App => {
return class Apollo extends React.Component {
static displayName = "withApollo(App)";
static async getInitialProps(ctx) {
const { Component, router } = ctx;
let appProps = {};
if (App.getInitialProps) {
appProps = await App.getInitialProps(ctx);
}
// Run all GraphQL queries in the component tree
// and extract the resulting data
const apollo = initApollo();
if (!process.browser) {
try {
// Run all GraphQL queries
await getDataFromTree(
<App
{...appProps}
Component={Component}
router={router}
apolloClient={apollo}
/>
);
+ await getMarkupFromTree({
+ renderFunction: renderToString,
+ tree: <App
+ {...appProps}
+ Component={Component}
+ router={router}
+ apolloClient={apollo}
+ />,
+ });
} catch (error) {
// Prevent Apollo Client GraphQL errors from crashing SSR.
// Handle them in components via the data.error prop:
// https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
console.error("Error while running `getDataFromTree`", error);
}
// getDataFromTree does not call componentWillUnmount
// head side effect therefore need to be cleared manually
Head.rewind();
}
// Extract query data from the Apollo store
const apolloState = apollo.cache.extract();
return {
...appProps,
apolloState
};
}
constructor(props) {
super(props);
this.apolloClient = initApollo(props.apolloState);
}
render() {
return <App {...this.props} apolloClient={this.apolloClient} />;
}
};
}; This has also been pointed out by another person in #52 (comment) |
Unfortunately, even with that change in place, my queries are still running after the page loads in the static HTML export, instead of having been fully rendered via the export process. |
Your scenario (not fully rendered) only happens once one or multiple graphql errors occurred during „getDataFromTree“ / „getMarkupFromTree“. Asides from that, I quickly just glanced over your code and you forgot to import the ApolloProvider of this module. ( See ) Add it to your existing providers in _app.js and add the snipet from above and you should be good to go. |
Thanks for the feedback, but still not getting a rendered export. I have checked for any graphql errors (there are none that I see in the console on any page), and I have imported the module you mentioned, and still have the same result. Is there a way to enable logging of graphql renders during build so I can make sure no pages are returning errors? The catch statement in
and
|
-<ApolloProvider client={{ wpClient, secondClient }}>
- <ApolloHooksProvider client={{ wpClient, secondClient }}>
<GlobalState>
<Layout>
<Component {...pageProps} />
</Layout>
</GlobalState>
</ApolloHooksProvider>
</ApolloProvider> These two lines look fishy, more precisely that you pass an object containing two clients. In the typings of this library and of apollo react one can see that only one apollo client is expected and not an object containing multiple. If you want to utilize multiple clients, consider using a composite link with two http links, each pointing to a different endpoint. |
Yep, two clients was the initial point of my question:
When I only had one client, I was getting static HTML renders no problem. This comment on this issue for react apollo was the inspiration for my going with the direction of putting two clients on the client object passed to This setup does indeed function, and I can run queries like so:
vs In any event, the composite link information you shared sent me down the right path, and was able to refactor using multiple links and Thanks for your help! |
In case anyone comes across this in the future, here is a write-up of the method I ended up using: https://www.loudnoises.us/next-js-two-apollo-clients-two-graphql-data-sources-the-easy-way/ |
@paulisloud you forgot the "getMarkupFromTree" and "renderToString" import in your blog post (in the final with-apollo-client.js file). |
Good catch, many thanks for taking the time to go through the post. Updated and added a hat tip @ThomasK33. |
In my project I have the following in place which forces me to not use Query, and instead in to a combination of ApolloConsumer + hooks in my components, which seems to not allow for fully rendered static HTML exports from next.
Why? Because I have two GraphQL data sources and need to be able to specify the client in the component, and Query doesn't take this parameter.
What follows is my code from the following files, in this order:
So, the end result is that whereas previously when using the Query component, with only one client, when I would run
next export
and get a fully rendered static HTML version of the page, now I have to wait for the fetch and render.I have read the documentation on the front page of this project for SSR, but I can't figure out how to include the call for getMarkupFromTree in this structure, and if I could, if that would do the trick.
Thanks for any advice.
The text was updated successfully, but these errors were encountered: