Next.js SSR + React server components - error ApolloProvider

Hello everyone, apologies for such a noob questions but while learning and playing with the Apollo React Client I keep having an error that I’m not sure how to handle.

Unhandled Runtime Error Error: Cannot read properties of undefined (reading 'Symbol(__APOLLO_CONTEXT__)')

I am trying to wrap the {children} in the layout.tsx, I am using both /app in nextjs 13.1 and react server components,

`import React from ‘react’
import Link from ‘next/link’
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
gql,
} from ‘@apollo/client’

let pokelist: any =

const client = new ApolloClient({
uri: ‘https://beta.pokeapi.co/graphql/v1beta’,
cache: new InMemoryCache(),
})

client
.query({
query: gql { gen3_species: pokemon_v2_pokemonspecies( limit: 69 order_by: { name: asc } ) { name id } } ,
})
.then((res) => (pokelist = res.data.gen3_species))

export default async function layout({
children,
}: {
children: React.ReactNode
}) {
// section for await
console.log(client)
return (




{children}


)
}
`

Hi @SGthatGui :wave: welcome to the community forum! React Server Components are stateless so any React hooks that contain hooks like useState and useContext can only be used on client components. That includes parts of the Apollo Client React API including ApolloProvider and hooks like useQuery. Hope that helps!

1 Like

One thing to think about here is that using SSR and server components is that there is no cache (@apollo/client’s cache doesn’t matter here because things are loading only once on the server - stateless).

I can think of three options you have here in the short term if you really want to use React server components today:

  1. If you don’t use ApolloProvider and instead pass the ApolloClient instance to useQuery directly:
const client = new ApolloClient({...});
...

const result = useQuery(MY_QUERY,{client});
  1. Use the query or mutate methods available on ApolloClient:
const client = new ApolloClient({...});
...

const result = await client.query({ query: MY_QUERY });
  1. Use something like urql for your server components and @apollo/client for the rest of your app.

I hope this helps and if you want to talk more about it live, we have a Discord server that you can join. Feel free to ping me (@watson)!

2 Likes

tyvm for your help and insight, makes perfect sense.
:wave:t2: howdy and thank you for the warm welcome, get ready for loads of these noob :sweat_smile: questions.

1 Like

let me begin for thanking you for your time and attention :hand_with_index_finger_and_thumb_crossed:
Will think about it and test out the different solutions you have depicted, good to stumble on these noob problems now as a lot of js frameworks are adopting new render and hydration methods, this is also my first contact with graphQL and Apollo :sweat_smile: still a lvl0 noob

1 Like

:heart: we’re always here to help level up! :muscle:

2 Likes
'use client'; 

import { ApolloProvider } from '@apollo/client'; 
import { client } from '@/graphQL/apollo-client';

interface IGraphQlProviderProps {
    children: React.ReactNode; 
}

const GraphQlProvider: React.FC<IGraphQlProviderProps> = ({
    children
}) => {
    return (
        <ApolloProvider client={client}>
            {children}
        </ApolloProvider>

    )
}

export default GraphQlProvider; 

Adding “use client” at the top of the provider cleared my error.

import AuthProvider from "@/providers/AuthProvider";
import "./globals.css";
import { Inter } from "next/font/google";
import UIProvider from "@/providers/UIProvider";
import GraphQlProvider from "@/providers/GraphQlProvider";

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

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

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

        <AuthProvider>
          <UIProvider>{children}</UIProvider>
        </AuthProvider>
        </GraphQlProvider>
      </body>
    </html>
  );
}


and then wrap in layout.tsx like this

1 Like