Error: (0 , _apollo_client_integration_nextjs__WEBPACK_IMPORTED_MODULE_2__.registerApolloClient) is not a function
Of course! Here's the English translation of your corrected and polished message:
We are trying to integrate the following versions:
"@apollo/client": "3.13.5",
"@apollo/client-integration-nextjs": "0.12.0"
However, we are finding the documentation very difficult to understand, as it is quite confusing and unclear.
Our issue arises when we try to use useApolloClient() from within a provider wrapped like this:
const ApolloWrapper = ({ children }: ApolloProviderProps) => {
return <ApolloNextAppProvider makeClient={getClient}>{children}</ApolloNextAppProvider>;
}
We’re getting the error shown in the attached image. We’ve followed your Next.js examples repeatedly (we’re using version 18), but we still can’t get it to work properly.
We have several questions we'd like to clarify:
- What is the correct way to make a client-side request using Apollo?
- Do the
apolloClientandApolloWrapperfiles need to be placed in a specific directory? - Should the
makeClientvalue inApolloWrapperbe the same as the one defined usingregisterApolloClient, or should we importgetClientfrom that file and pass it directly asmakeClient? - Server-side requests are working fine — the issue is only on the client side.
We would greatly appreciate a clear explanation or an up-to-date working example. Thank you very much for your support.
Did you maybe mix server code and client code in the same file?
ApolloWrapper needs to be in a file with "use client" at the top.
registerApolloClient needs to be in a server file, though.
That means a file without "use client", and that file must never be imported by a file with "use client" at the top, and never be imported by a file that is imported by a file with "use client" at the top (etc.).
As "use client" is "spreading" that way, it would turn the server file into a client file.
It seems that here you create some kind of import chain from a "use client" file to your registerApolloClient call.
👋 Hi there!
We’ve split our Apollo Client setup like this:
src/lib/apollo/apolloClient.ts
import { signOut } from 'next-auth/react'
import { ROUTES } from '@/utils/constants/routes'
import {
ApolloError,
ApolloLink,
FetchResult,
HttpLink,
NextLink,
Operation,
} from '@apollo/client'
import {
ApolloClient,
InMemoryCache,
registerApolloClient,
} from '@apollo/client-integration-nextjs'
import 'cross-fetch/polyfill'
import { GRAPHQL_AUTHORIZATION_ERROR } from './constants/graphql-errors'
const httpLink = new HttpLink({
uri: `${process.env.NEXT_PUBLIC_BACKEND_URL}/graphql`,
headers: {},
})
const verifyGraphQLErrors = new ApolloLink((operation: Operation, forward: NextLink) => {
return forward(operation).map((response: FetchResult) => {
if (response?.errors && response?.errors[0]) {
switch (response.errors[0]?.extensions?.category) {
case GRAPHQL_AUTHORIZATION_ERROR:
if (typeof localStorage !== 'undefined') {
signOut({
callbackUrl: `/${window.location.pathname.split('/')[1]}${ROUTES.SIGN_OUT}?error=invalidToken`,
}).catch(console.error)
}
break
default:
throw new ApolloError({
graphQLErrors: response.errors,
errorMessage: response.errors?.[0]?.message || 'Error',
})
}
}
return response
})
})
export const { getClient, query, PreloadQuery } = registerApolloClient(() => {
return new ApolloClient({
link: verifyGraphQLErrors.concat(httpLink),
cache: new InMemoryCache({ addTypename: false }),
defaultOptions: {
mutate: { fetchPolicy: 'no-cache', errorPolicy: 'all' },
query: { fetchPolicy: 'no-cache', errorPolicy: 'all' },
},
})
})
src/lib/apollo/ApolloWrapper.tsx
'use client'
import { ReactNode } from 'react'
import {
ApolloClient,
ApolloNextAppProvider,
InMemoryCache,
} from '@apollo/client-integration-nextjs'
import {
ApolloError,
ApolloLink,
FetchResult,
HttpLink,
NextLink,
Operation,
} from '@apollo/client'
import { GRAPHQL_AUTHORIZATION_ERROR } from '@/lib/apollo/constants/graphql-errors'
import { signOut } from 'next-auth/react'
import { ROUTES } from '@/utils/constants/routes'
interface ApolloProviderProps {
children: ReactNode
}
function makeClient() {
const httpLink = new HttpLink({
uri: `${process.env.NEXT_PUBLIC_BACKEND_URL}/graphql`,
headers: {},
})
const verifyGraphQLErrors = new ApolloLink((operation: Operation, forward: NextLink) => {
return forward(operation).map((response: FetchResult) => {
if (response?.errors && response?.errors[0]) {
switch (response.errors[0]?.extensions?.category) {
case GRAPHQL_AUTHORIZATION_ERROR:
if (typeof localStorage !== 'undefined') {
signOut({
callbackUrl: `/${window.location.pathname.split('/')[1]}${ROUTES.SIGN_OUT}?error=invalidToken`,
}).catch(console.error)
}
break
default:
throw new ApolloError({
graphQLErrors: response.errors,
errorMessage: response.errors?.[0]?.message || 'Error',
})
}
}
return response
})
})
return new ApolloClient({
link: verifyGraphQLErrors.concat(httpLink),
cache: new InMemoryCache({ addTypename: false }),
defaultOptions: {
mutate: { fetchPolicy: 'no-cache', errorPolicy: 'all' },
query: { fetchPolicy: 'no-cache', errorPolicy: 'all' },
},
})
}
const ApolloWrapper = ({ children }: ApolloProviderProps) => {
return <ApolloNextAppProvider makeClient={makeClient}>{children}</ApolloNextAppProvider>
}
export default ApolloWrapper
These are completely separated.
But when we use this in a page:
<ApolloWrapper>
<Suspense fallback={<>Loading</>}>
<WebSettingsContextProvider>{children}</WebSettingsContextProvider>
</Suspense>
</ApolloWrapper>
And inside WebSettingsContextProvider we use:
'use client'
import { useApolloClient } from '@apollo/client'
import { Session } from 'next-auth'
import { Store } from '@/types/ContextOptions'
import { customContext } from '@/utils/customContext'
import { OperationNames } from '../operationNames'
import {
GetWebSettingsDocument,
GetWebSettingsQuery,
} from '@/lib/graphql-operations'
import { ApolloQueryResult } from '@apollo/client'
export const useQueryGetWebSettings = () => {
const apolloClient = useApolloClient()
return async (session: Session | null, store: Store): Promise<ApolloQueryResult<GetWebSettingsQuery>> => {
const context = customContext({
operationName: OperationNames._QUERY_GET_WEB_SETTINGS,
session,
store,
})
return await apolloClient.query({
query: GetWebSettingsDocument,
context,
})
}
}
We assumed that since this component is under <ApolloWrapper>, useApolloClient() would use the correct client. However, we keep getting this error:
Unhandled Runtime Error
Error: (0 , _apollo_client_integration_nextjs__WEBPACK_IMPORTED_MODULE_2__.registerApolloClient) is not a function
src/lib/apollo/apolloClient.ts (33:71)
Whether we wrap it in Suspense or not, it doesn’t work.
We’ve checked the official examples from the repo, but none of them have helped so far: 👉 https://github.com/apollographql/apollo-client-integrations/tree/%40apollo/client-integration-nextjs%400.12.0/examples
Versions:
"@apollo/client": "3.13.5",
"@apollo/client-integration-nextjs": "0.12.0",
"next": "15.2.5",
"next-auth": "4.24.11",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-cookie": "8.0.1",
"react-gtm-module": "2.0.11",
"react-intl": "7.1.10",
"react-jsbarcode": "1.0.1",
"react-modal": "3.16.3",
"react-range": "1.10.0",
"react-slick": "0.30.3",
"react-to-print": "3.0.5",
"react-waypoint": "10.3.0",
"react-zendesk": "0.1.13"
Any help would be appreciated 🙏
@DanielGBullido
Versions:
"next": "15.2.5", "next-auth": "4.24.11", "react": "18.3.1", "react-dom": "18.3.1",
to my knowledge you can't use React 18 with Next 15? https://nextjs.org/docs/app/guides/upgrading/version-15#react-19
We are encountering the same error.
It seems the logic is trying to import from @apollo/client-integration-nextjs/dist/index.browser.js instead of index.rsc.js from what I gathered.
Also verified with AI that our separation between server and client files is correct.
It seems the logic is trying to import from @apollo/client-integration-nextjs/dist/index.browser.js instead of index.rsc.js from what I gathered.
Yes, that's what happens if you are in a client file. It imports the index.browser.js in client files and the index.rsc.js in RSC.
If you look at
https://github.com/apollographql/apollo-client-integrations/blob/c465affd9e31674e868cdc7ac90cf0cab4c7f70e/packages/nextjs/package.json#L45-L47
you will see that react-server has a higher priority than browser, so if you are in an RSC environment, you bundler will pick up the RSC import.
Also verified with AI that our separation between server and client files is correct.
I fear AI is probably missing something there :/
You can try to add import 'server-only' at the top of the files you want to be server only. If you get an error message regarding that, they are in fact imported from a client import path.