I have created a next js 14.2.3 app & I have graphql api end point(** which I replaced with localhost for stackOverflow )and I am using "@apollo/client":"^3.10.3"
, "graphql":"^16.8.1"
, for fetching data. I have created a product page path "pages/products".
import { useQuery, gql } from "@apollo/client";
import { initializeApollo } from "../lib/apollo-client";
const PRODUCTS_QUERY = gql`
query Products {
products(first: 10, channel: "default-channel") {
edges {
node {
id
name
}
}
}
}
`;
function Products() {
const apolloClient = initializeApollo();
const { data, loading, error } = useQuery(PRODUCTS_QUERY, {
client: apolloClient,
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Products</h1>
<ul>
{data &&
data.products.edges.map(({ node }) => (
<li key={node.id}>{node.name}</li>
))}
</ul>
</div>
);
}
export default Products;
I have created a apollo-client,js file
import { useMemo } from "react";
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
let apolloClient;
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: new HttpLink({
uri: "http://localhost:8000/graphql/",
}),
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;
}
so when I am routing http://localhost:3000/pages/products
I think this is because <Products />
component currently rendered as server component. And Contexts is not avaliable for server components.
There are two ways to fix it:
is to make this component client by adding "use client"
on top of pages/products
.
Rewrite the component to use apollo client directly without relying on useQuery hook. Here is a good artlice explaining how to do it.
Crud example:
import { gql } from "@apollo/client";
import { initializeApollo } from "../lib/apollo-client";
const PRODUCTS_QUERY = gql`
query Products {
products(first: 10, channel: "default-channel") {
edges {
node {
id
name
}
}
}
}
`;
async function Products() {
const apolloClient = initializeApollo();
const { data } = await apolloClient.query({
query: PRODUCTS_QUERY,
context: {},
});
return (
<div>
<h1>Products</h1>
<ul>
{data?.products?.edges?.map(({ node }) => (
<li key={node.id}>{node.name}</li>
))}
</ul>
</div>
);
}
export default Products;