Search code examples
reactjsgraphqlnext.jsreact-apollostrapi

Recommended way to use GraphQL in Next.js app


In my apps, I am using following NPM modules to play with Strapi, GraphQL and Next.js:

In the next step, I am creating Apollo config file, example below:

import { HttpLink } from "apollo-link-http";
import { withData } from "next-apollo";

const config = {
  link: new HttpLink({
    uri: "http://localhost:1337/graphql",
  })
};
export default withData(config);

and then inside a class component, I am using a static method getInitialProps() to fetch data from the Strapi via GraphQL query.

Everything is fine but maybe there is another, better way via React hooks or any other?


Solution

  • 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:

    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..