Currently, I am making adjustments to my NextJS/Apollo application to enable SSG with GraphQL API routes. I have referenced this official NextJS starter example as a foundation for configuring the client.
An issue arose in my application which led me to go back to the starter example to try and replicate it, successfully. The problem arises when a context object is introduced to the query resolvers. Surprisingly, everything functions correctly without the context object (in both the playground and client). However, once a context object is incorporated and passed to the resolvers, it works properly in the playground but the context object is undefined when triggered from the client. Below is the code snippet from the official NextJS starter example with my annotations:
graphql.js
import { ApolloServer } from "apollo-server-micro";
import { schema } from "../../apollo/schema";
const apolloServer = new ApolloServer({
schema,
context: { //
foo: "bar", // this is the context object I've added
}, //
});
export const config = {
api: {
bodyParser: false,
},
};
export default apolloServer.createHandler({ path: "/api/graphql" });
typedefs.js
import { gql } from '@apollo/client'
export const typeDefs = gql`
type User {
id: ID!
name: String!
status: String!
}
type Query {
viewer: User
}
`
Despite receiving the correct response when querying the API in the GraphQL playground and seeing the context foo: bar
object in the console log in the server, the context object returns undefined in the browser when visiting the index page, as shown below:
index.js
import gql from "graphql-tag";
import Link from "next/link";
import { useQuery } from "@apollo/client";
import { initializeApollo } from "../apollo/client";
const ViewerQuery = gql`
query ViewerQuery {
viewer {
id
name
status
}
}
`;
const Index = () => {
const {
data: { viewer },
} = useQuery(ViewerQuery);
return (
<div>
You're signed in as {viewer.name} and you're {viewer.status} goto{" "}
<Link href="/about">
<a>static</a>
</Link>{" "}
page.
</div>
);
};
export async function getStaticProps() {
const apolloClient = initializeApollo();
await apolloClient.query({
query: ViewerQuery,
});
return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
};
}
export default Index;
Although the viewer name and status are correctly rendered, the console log for the context
object displays undefined
. This discrepancy is intriguing, especially considering this is an official NextJS starter example. I am unsure why the client setup may not be accepting context in the resolvers. If this is indeed the issue, I am curious if there are other official examples with a client setup that does support resolver context input.
While this is quite a lengthy query, here is the snippet for client.js
:
import { useMemo } from "react";
import { ApolloClient, InMemoryCache } from "@apollo/client";
let apolloClient;
function createIsomorphLink() {
if (typeof window === "undefined") {
const { SchemaLink } = require("@apollo/client/link/schema");
const { schema } = require("./schema");
return new SchemaLink({ schema });
} else {
const { HttpLink } = require("@apollo/client/link/http");
return new HttpLink({
uri: "http://localhost:3000/api/graphql",
credentials: "same-origin",
});
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: createIsomorphLink(),
cache: new InMemoryCache(),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState);
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === "undefined") return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
If anyone can clone this official repository and provide insights on how to resolve the context issue in the client, or if there are other client setups that accept resolver context, I welcome your input. This problem has been puzzling me for the past two days!