Search code examples
reactjsnext.jsapollo-clientgraphqlclient

Unable to Setup Next.js 14 with Apollo Client GraphQL


I am new to Next.js & GraphQL, need to work on a project using both. So trying to setup a dummy project with Next.js(JavaScript, React), Apollo Client, Apollo Server. The Server side is up and running without hassle. But Client side is not able to load Apollo Server data in UI, I was able create a basic API call from client side and load the data but not able to make it render using ApolloProvider / ApolloWrapper.

I have tried to follow many articles available online, but none worked. The final one which looked promising and easy but written for TypeScript - Medium Article & Repo. I tried to follow it but still getting below error:

Error Message

src/app/layout.js

import { Inter } from "next/font/google";
import "./globals.css";
import { ApolloProvider } from "@apollo/client";
// import { ApolloWrapper } from "../lib/apollo-wrapper";
import client from "../lib/client";


const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
      <html lang="en">
        <body className={inter.className}>
          <ApolloProvider client={client}>{children}</ApolloProvider>
        </body>
      </html>
  );
}

src/lib/client.js

import { ApolloClient, HttpLink, InMemoryCache, from } from "@apollo/client";

const httpLink = new HttpLink({
  uri: '/'
})

const client = new ApolloClient({
    cache: new InMemoryCache(),
    uri: "http://localhost:4000/",
    link: from([httpLink])
  });
  
export default client;

Dependencies from package.json

  "dependencies": {
    "@apollo/client": "^3.9.0-rc.1",
    "@apollo/experimental-nextjs-app-support": "^0.8.0",
    "graphql": "^16.8.1",
    "next": "14.1.0",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "autoprefixer": "^10.0.1",
    "eslint": "^8",
    "eslint-config-next": "14.1.0",
    "postcss": "^8",
    "tailwindcss": "^3.3.0"
  }

Solution

  • If you want to use Apollo Client with the App Router, you have to use it with the @apollo/experimental-nextjs-app-support library. Refer to this post - NextJS (AppRouter), Apollo (Client), error on using ApolloProvider in root layout

    Seems like you added @apollo/experimental-nextjs-app-support in your dependencies but didn't use it at all. Also, your @apollo/client library may need to be updated to the latest version - npm install @apollo/client@latest

    To wrap your RootLayout with ApolloProvider, try following (refer to https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support for more info):

    First, create a new file src/app/ApolloWrapper.jsx:

    "use client";
    
    import { ApolloLink, HttpLink } from "@apollo/client";
    import {
      ApolloNextAppProvider,
      NextSSRInMemoryCache,
      NextSSRApolloClient,
      SSRMultipartLink,
    } from "@apollo/experimental-nextjs-app-support/ssr";
    
    function makeClient() {
      const httpLink = new HttpLink({
        uri: "http://localhost:4000/api/graphql",
        fetchOptions: { cache: "no-store" },
      });
    
      return new NextSSRApolloClient({
        cache: new NextSSRInMemoryCache(),
        link:
          typeof window === "undefined"
            ? ApolloLink.from([
                new SSRMultipartLink({
                  stripDefer: true,
                }),
                httpLink,
              ])
            : httpLink,
      });
    }
    
    export function ApolloWrapper({ children }) {
      return (
        <ApolloNextAppProvider makeClient={makeClient}>
          {children}
        </ApolloNextAppProvider>
      );
    }
    

    Now you can wrap your RootLayout in this wrapper component in the src/app/layout.js file:

    import { Inter } from "next/font/google";
    import "./globals.css";
    import { ApolloWrapper } from "./ApolloWrapper";
    
    const inter = Inter({ subsets: ["latin"] });
    
    export const metadata = {
      title: "Create Next App",
      description: "Generated by create next app",
    };
    
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>
            <ApolloWrapper>{children}</ApolloWrapper>
          </body>
        </html>
      );
    }