简体   繁体   中英

How to hydrate Apollo client from NextJS server

I am using a custom NextJS server with Apollo Client. I want to fetch the GraphQL data server-side and then send it to the client. I was kind of able to do that, but the client-side fetches it again. I understand that the Apollo cache is available only on the server, then needs to be sent to the client and restored from there.

The Apollo docs mention SSR but I don't want to fully render my app using the Apollo client, I want to use NextJS, I want to get just the data from the Apollo client and manually inject it into the HTML to restore it on the client. I looked at some examples for NextJS using Apollo, but none of them showed how to do exactly that.

This is my custom handler for requests:

const app = next({ dev: process.env.NODE_ENV !== 'production' });

const customHandler = async (req, res) => {
  const rendered = await app.renderToHTML(req, res, req.path, req.query);
  // somehow get the data from the apollo cache and inject it in the rendered html
  res.send(rendered);
}

When you create the ApolloClient in the server, you can pass the initialState to hydrate the cache.

const createApolloClient = ({ initialState, headers }) =>
    new ApolloClient({
      uri: GRAPHQL_URL,
      cache: new InMemoryCache().restore(initialState || {}) // hydrate cache
    });

export default withApollo(PageComponent, { ssr = true } = {}) => {

  const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
    const client = apolloClient || createApolloClient({ initialState: apolloState, headers: {} });

     ... rest of your code. 
  });
});

I have created a package just for this called nextjs-with-apollo . Take a look at https://github.com/adikari/nextjs-with-apollo . Once you have installed the package create a HOC as such.

// hocs/withApollo.js
import withApollo from 'nextjs-with-apollo';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';

const GRAPHQL_URL = 'https://your-graphql-url';

const createApolloClient = ({ initialState, headers }) =>
    new ApolloClient({
      uri: GRAPHQL_URL,
      cache: new InMemoryCache().restore(initialState || {}) // hydrate cache
    });

export default withApollo(createApolloClient);

Then you can use the hoc for your next page as such.

import React from 'react';
import { useQuery } from '@apollo/react-hooks';

import withApollo from 'hocs/withApollo';

const QUERY = gql`
  query Profile {
    profile {
      name
      displayname
    }
  }
`;

const ProfilePage = () => {
  const { loading, error, data } = useQuery(PROFILE_QUERY);

  if (loading) {
    return <p>loading..</p>;
  }

  if (error) {
    return JSON.stringify(error);
  }

  return (
    <>
      <p>user name: {data.profile.displayname}</p>
      <p>name: {data.profile.name}</p>
    </>
  );
};

export default withApollo(ProfilePage);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM