How to Add Apollo Client to Your Next.js App

Apollo Client is a state management library built to work with GraphQL APIs. It provides many built-in features that help with data fetching, caching, and state management for both local and remote data. The library supports many popular frontend frameworks like React. In this blog we will be learning how to add Apollo Client to your Next.js App.

Jordan Wu profile picture

Jordan Wu

4 min·Posted 

Great Smoky Mountains National Park, United States Image.
Great Smoky Mountains National Park, United States Image.
Table of Contents

What is an Apollo Client?

Apollo Client is a state management library written in JavaScript. It is used to handle requests to a GraphQL API and manages the response data into caches. Many features are provided out of the box to help make working with GraphQL a breeze. This allows developers to focus on building what is important. Many companies are using GraphQL APIs and Apollo Client is playing a critical role in the development of great software applications.

How to Add Apollo Client to Next.js App Router

This blog is based on How to Add GraphQL to Your Next.js App and assumes you already created a GraphQL API in your Next.js app. For this part it will be focused on setting up Apollo Client and then storing the user's email address for a newsletter.

Setup

Install the following dependencies:

pnpmyarnnpm
pnpm add @apollo/client @apollo/experimental-nextjs-app-support

Next add the following environment variable called NEXT_PUBLIC_ENDPOINT_GRAPHQL_URI to your environment file, .env. NEXT_PUBLIC prefix is used because this environment variable will be used on the client and follows Next.js Building Environment Variables for the Browser.

.env
NEXT_PUBLIC_ENDPOINT_GRAPHQL_URI="http://localhost:3000/api/graphql"

Be sure to add the environment variable to your cloud deployment platform, for me that will be Vercel, Declare an Environment Variable.

Create Apollo Client For Server Component

Create apollo-client.ts in the lib directory.

File Imagesrc/lib/apollo-client.ts
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support/rsc'

export const { getClient } = registerApolloClient(() => {
  return new ApolloClient({
    cache: new InMemoryCache(),
    link: new HttpLink({
      uri: process.env.NEXT_PUBLIC_ENDPOINT_GRAPHQL_URI,
    }),
  })
})

This created a simple Apollo Client that uses the default in-memory cache and will be making request to our GraphQL endpoint at http://localhost:3000/api/graphql. @apollo/experimental-nextjs-app-support/rsc was added to support Apollo Client for Next.js App Router architecture for React Server Components RSC.

You can now use that getClient function in your server components:

const { data } = await getClient().query({ query: userQuery });

Create Apollo Provider

For our client components to use Apollo Client you need to create a provider called ApolloProvider.tsx.

File Imagesrc/providers/ApolloProvider.tsx
'use client'
import { ApolloLink, HttpLink } from '@apollo/client'
import {
  ApolloNextAppProvider,
  NextSSRInMemoryCache,
  NextSSRApolloClient,
  SSRMultipartLink,
} from '@apollo/experimental-nextjs-app-support/ssr'

import type { ReactNode } from 'react'

function makeClient() {
  const httpLink = new HttpLink({
    uri: process.env.NEXT_PUBLIC_ENDPOINT_GRAPHQL_URI,
    fetchOptions: { cache: 'no-store' },
  })

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === 'undefined'
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  })
}

type ApolloProviderProps = {
  children: ReactNode
}

export default function ApolloProvider(props: ApolloProviderProps) {
  const { children } = props

  return <ApolloNextAppProvider makeClient={makeClient}>{children}</ApolloNextAppProvider>
}

This provider will give all your client components access to the Apollo Client and is required if you use App Router. Now with the provider defined, add it to the root layout file layout.tsx.

File Imagesrc/app/layout.tsx
import ApolloProvider from '@/providers/ApolloProvider'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang="en">
      <body>
        <ApolloProvider>{children}</ApolloProvider>
      </body>
    </html>
  );
}

That's everything you need to setup Apollo Client in your Next.js app!

Store User Email For Newsletter

To test the Apollo Client you will be creating a component to handle users subscribing to your newsletter. First you need to create a mutation query called subscribeUserEmail.ts.

File Imagesrc/app/api/graphql/mutations/subscribeUserEmail.ts
import { gql } from '@apollo/client'

export default gql`
  mutation subscribeUserEmail($email: String!) {
    subscribeUserEmail(email: $email) {
      ... on Error {
        message
      }
      ... on SubscribeUserEmail {
        data {
          email
        }
      }
    }
  }
`

This mutation query is used to make a request to our Next.js server and save the user's email address to the users database. It will be used in SubscribeUserEmailForm.tsx component.

File Imagesrc/components/subscribe-user-email-form/subscribe-user-email-form.tsx
'use client'
import { useRef, useState, memo, useCallback } from 'react'
import Image from 'next/image'
import { useMutation } from '@apollo/client'
import SubscribeUserEmailMutation from '@/grapqhl/mutations/subscribeUserEmail'
import Snackbar from '@/components/snackbar'

function SubscribeUserEmailForm() {
  const [showSnackbar, setShowSnackbar] = useState(false)
  const [snackbarMessage, setSnackbarMessage] = useState('')
  const inputRef = useRef<HTMLInputElement | null>(null)
  const [subscribeUserEmail] = useMutation(SubscribeUserEmailMutation, {
    onCompleted: (data) => {
      const { subscribeUserEmail } = data

      if (subscribeUserEmail?.message) {
        setSnackbarMessage(subscribeUserEmail.message)
      } else {
        setSnackbarMessage('You successfully subscribed!')
      }

      if (inputRef.current) {
        inputRef.current.value = ''
      }

      setShowSnackbar(true)
    },
  })

  const handleFormSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()

    const userEmail = inputRef.current?.value

    const options = {
      variables: {
        email: userEmail,
      },
    }
    subscribeUserEmail(options)
  }

  const handleSnackbarClose = useCallback(() => {
    setShowSnackbar(false)
  }, [])

  return (
    <div className="rounded-2xl border border-zinc-700/40 p-6">
      <div className="flex text-sm font-semibold leading-6">
        <figure>
          <picture>
            <Image src="/icons/email.svg" alt="Email icon image" width={24} height={24} />
          </picture>
        </figure>
        <span className="ml-3">Stay up to date</span>
      </div>
      <p className="mt-2 text-sm text-zinc-400">
        Get notified when I publish something new, and unsubscribe at any time.
      </p>
      <form className="mt-6 flex" onSubmit={handleFormSubmit}>
        <input
          ref={inputRef}
          aria-label="Email Address"
          autoComplete="email"
          className="mr-2 inline-block rounded-md border border-zinc-700 bg-zinc-700/[0.15] px-3 text-zinc-200 shadow-zinc-800/5 outline-none placeholder:text-zinc-500 md:w-full"
          name="email"
          placeholder="Email address"
          type="email"
          required
        />
        <button type="submit" className="btn text-sm">
          Join
        </button>
      </form>
      {showSnackbar && <Snackbar message={snackbarMessage} onClose={handleSnackbarClose} />}
    </div>
  )
}

export default memo(SubscribeUserEmailForm)

This is a simple form component that will save the user's email address to our users table in a Postgres database using useMutation hook. It will show a snackbar with a message of "You successfully subscribed!" when it's completed.

Summary

Hope this blog post is helpful. With this information you should be able to start adding features to your Next.js app. A common feature in many blogging websites is a newsletter. Having a simple form to capture user email addresses for your newsletter will help inform them on updates, news, and information on specific topics. You can use services like Mailchimp for Email Marketing.

About the Author

Jordan Wu profile picture
Jordan is a full stack engineer with years of experience working at startups. He enjoys learning about software development and building something people want. What makes him happy is music. He is passionate about finding music and is an aspiring DJ. He wants to create his own music and in the process of finding is own sound.
Email icon image
Stay up to date

Get notified when I publish something new, and unsubscribe at any time.