apollo-client-nextjs: registerApolloClient is not a function (Runtime error)
Hey there. This is a first time I’m using Next JS 14 and Apollo client. I’ve done ApolloProvider and apollo-client.ts like in the documentation. In MainIntro I use an SSR request to preload the data that I use in the child component. The Header component must be client-side because I’m going to use hooks. As soon as I add “use client” to Header.tsx, I get the described error. Please help, below I post the component code and errors.
error
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({
// this needs to be an absolute url, as relative urls cannot be used in SSR
uri: process.env.API_URL,
// you can disable result caching here if you want to
// (this does not work if you are rendering your page with `export const dynamic = "force-static"`)
// fetchOptions: { cache: "no-store" },
}),
});
});
apollo-wrapper.tsx
"use client";
// ^ this file needs the "use client" pragma
import { ApolloLink, HttpLink } from "@apollo/client";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
NextSSRApolloClient,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
// have a function to create a client for you
function makeClient() {
const httpLink = new HttpLink({
// this needs to be an absolute url, as relative urls cannot be used in SSR
uri: "http://localhost:3000/api/graphql",
// you can disable result caching here if you want to
// (this does not work if you are rendering your page with `export const dynamic = "force-static"`)
fetchOptions: { cache: "no-store" },
// you can override the default `fetchOptions` on a per query basis
// via the `context` property on the options passed as a second argument
// to an Apollo Client data fetching hook, e.g.:
// const { data } = useSuspenseQuery(MY_QUERY, { context: { fetchOptions: { cache: "force-cache" }}});
});
return new NextSSRApolloClient({
// use the `NextSSRInMemoryCache`, not the normal `InMemoryCache`
cache: new NextSSRInMemoryCache(),
link:
typeof window === "undefined"
? ApolloLink.from([
// in a SSR environment, if you use multipart features like
// @defer, you need to decide how to handle these.
// This strips all interfaces with a `@defer` directive from your queries.
new SSRMultipartLink({
stripDefer: true,
}),
httpLink,
])
: httpLink,
});
}
// you need to create a component to wrap your app in
export function ApolloWrapper({ children }: React.PropsWithChildren) {
return (
<ApolloNextAppProvider makeClient={makeClient}>
{children}
</ApolloNextAppProvider>
);
}
lauout.tsx
export default function RootLayout({
children,
params: { locale },
}: Readonly<Props>) {
return (
<html lang={locale}>
<body className={inter.className}>
<ApolloWrapper>
<Header />
<main>{children}</main>
<Footer />
</ApolloWrapper>
</body>
</html>
);
}
page.tsx
import { MainIntro } from "@/components";
const HomePage = () => {
return (
<>
<MainIntro />
</>
);
};
export default HomePage;
MainIntro.tsx
import { gql } from "@apollo/client";
import { getTranslations, getMessages } from "next-intl/server";
import { NextIntlClientProvider } from "next-intl";
import pick from "lodash/pick";
import { getClient } from "@/configs";
import { Container } from "@/components";
import { FilterClient } from "./components";
import styles from "./MainIntro.module.css";
const MainIntro = async () => {
const t = await getTranslations("Homepage");
const messages = await getMessages();
const { data } = await getClient().query({
query: FILTER_QUERY,
context: {
fetchOptions: {
next: { revalidate: 3600 },
},
},
});
return (
<section className={styles.section}>
<Container className={styles.container}>
<h1 className={styles.title}>{t("title")}</h1>
<p className={styles.description}>
Discover your perfect match in healthcare with our service, where
finding a trusted specialist is both convenient and swift, ensuring
peace of mind with every choice
</p>
<NextIntlClientProvider messages={pick(messages, "Global")}>
<FilterClient data={data} />
</NextIntlClientProvider>
</Container>
</section>
);
};
const FILTER_QUERY = gql`
query Query {
countries {
id
code
}
specialties {
id
key
}
}
`;
export default MainIntro;
header.tsx
"use client"
import React from "react";
import Link from "next/link";
import Image from "next/image";
import styles from "./header.module.css";
import { Container } from "@/components";
import { LangSwitcher } from "./components";
type Props = {
simple?: boolean;
};
const Header:React.FC<Props> = ({ simple }) => {
return (
<header className={styles.section}>
<Container className={styles.wrapper}>
<Link href="/" className={styles.logo} aria-label="Veso Health Logo">
<Image
src="/veso-logo.svg"
width={103}
height={34}
alt="Veso Health Logo"
priority={true}
/>
</Link>
{!simple && <LangSwitcher />}
</Container>
</header>
);
};
export default Header;
About this issue
- Original URL
- State: closed
- Created 3 months ago
- Comments: 18 (8 by maintainers)
Thanks for your help