Recommended way to use GraphQL in Next.js app

I found one more nice hook solution for Next.js and GraphQL.

I want to share it with you. Let's start.

Note: I assume that you have Next.js application already installed. If not please follow this guide.

To build this solution we need:

  • @apollo/react-hooks
  • apollo-cache-inmemory
  • apollo-client
  • apollo-link-http
  • graphql
  • graphql-tag
  • isomorphic-unfetch
  • next-with-apollo

1. run npm command:

npm install --save @apollo/react-hooks apollo-cache-inmemory apollo-client apollo-link-http graphql graphql-tag isomorphic-unfetch next-with-apollo

2. create Appolo config file, eg. in folder ./config and call it appollo.js. File code below:

import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import withApollo from "next-with-apollo";
import { createHttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";

const GRAPHQL_URL = process.env.BACKEND_URL || "https://api.graphql.url";

const link = createHttpLink({
  fetch,
  uri: GRAPHQL_URL
});

export default withApollo(
  ({ initialState }) =>
    new ApolloClient({
      link: link,
      cache: new InMemoryCache()
        .restore(initialState || {})
    })
);

3. create _app.js file (kind of wrapper) in ./pages folder with below code:

import React from "react";
import Head from "next/head";
import { ApolloProvider } from "@apollo/react-hooks";
import withData from "../config/apollo";

const App = ({ Component, pageProps, apollo }) => {
  return (
    <ApolloProvider client={apollo}>
      <Head>
        <title>App Title</title>
      </Head>
      <Component {...pageProps} />
    </ApolloProvider>
  )
};

export default withData(App);

4. create reusable query component, eg. ./components/query.js

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

const Query = ({ children, query, id }) => {  
  const { data, loading, error } = useQuery(query, {
    variables: { id: id }
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {JSON.stringify(error)}</p>;
  return children({ data });
};

export default Query;

5. create a component for our data fetched via GraphQL

import React from "react";
import Query from "../components/query";
import GRAPHQL_TEST_QUERY from "../queries/test-query";

const Example = () => {  
  return (
    <div>
      <Query query={GRAPHQL_TEST_QUERY} id={null}>
        {({ data: { graphqlData } }) => {
          return (
            <div>
              {graphqlData.map((fetchedItem, i) => {
                return (
                  <div key={fetchedItem.id}>
                    {fetchedItem.name}
                  </div>
                );
              })}
            </div>
          );
        }}
      </Query>
    </div>
  );
};

export default Example;

6. create our GraphQL query inside ./queries/test-query. Note: I assume that we have access to our example data and properties id and name via GraphQL

import gql from "graphql-tag";

const GRAPHQL_TEST_QUERY = gql`
  query graphQLData {
    exampleTypeOfData {
      id
      name
    }
  }
`;

export default GRAPHQL_TEST_QUERY;

7. to display our result create index.js file (homepage) in ./pages folder with below code:

import Example from './components/example';

const Index = () => <div><Example /></div>

export default Index;

That's all.. enjoy and extend this solution as you want..