Best practise to fetch GraphQL data only once on a dynamic route and pass it to "generateMetadata"
Answered
Barbary Lion posted this in #help-forum
Barbary LionOP
Hey, what is the best way to fetch GraphQL data via a dynamic route and then pass it to the main function of the server component as well as to "generateMetadata"?
On a dynamic route (app directory - page.tsx), I can access the "params" object only inside of "generateMetadata" and the default component, which results in having to perform two fetches. One inside of "generateMetadata" and one inside of the default component. But there must be a way to only fetch the data once and the pass it on to generateMetadata as well as the default component.
but how?
On a dynamic route (app directory - page.tsx), I can access the "params" object only inside of "generateMetadata" and the default component, which results in having to perform two fetches. One inside of "generateMetadata" and one inside of the default component. But there must be a way to only fetch the data once and the pass it on to generateMetadata as well as the default component.
but how?
Answered by joulev
use
React.cache to ensure the query only runs once despite being called multiple times.import { cache } from 'react'
import db from '@/lib/db'
const getItem = cache(async (id: string) => {
console.log("This is only run once");
const item = await db.item.findUnique({ id })
return item
})
export default async function Page() {
const data = await getItem("foo");
// ...
}
export async function generateMetadata() {
const data = await getItem("foo");
// ...
}7 Replies
@Barbary Lion Hey, what is the best way to fetch GraphQL data via a dynamic route and then pass it to the main function of the server component as well as to "generateMetadata"?
On a dynamic route (app directory - page.tsx), I can access the "params" object only inside of "generateMetadata" and the default component, which results in having to perform two fetches. One inside of "generateMetadata" and one inside of the default component. But there must be a way to only fetch the data once and the pass it on to generateMetadata as well as the default component.
but how?
use
React.cache to ensure the query only runs once despite being called multiple times.import { cache } from 'react'
import db from '@/lib/db'
const getItem = cache(async (id: string) => {
console.log("This is only run once");
const item = await db.item.findUnique({ id })
return item
})
export default async function Page() {
const data = await getItem("foo");
// ...
}
export async function generateMetadata() {
const data = await getItem("foo");
// ...
}Answer
Barbary LionOP
ok, thanks.
Well, I have cache activated in my ApolloClient. So I think this should than do the trick, too?
Well, I have cache activated in my ApolloClient. So I think this should than do the trick, too?
import { HttpLink } from "@apollo/client";
import {
registerApolloClient,
ApolloClient,
InMemoryCache,
} from "@apollo/experimental-nextjs-app-support";
export const { getClient, query, PreloadQuery } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "https://graphql.example.com/graphql",
}),
});
});@Barbary Lion ok, thanks.
Well, I have cache activated in my ApolloClient. So I think this should than do the trick, too?
import { HttpLink } from "@apollo/client";
import {
registerApolloClient,
ApolloClient,
InMemoryCache,
} from "@apollo/experimental-nextjs-app-support";
export const { getClient, query, PreloadQuery } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "https://graphql.example.com/graphql",
}),
});
});
i'm not sure, that's a different type of cache afaik so likely it won't work.
well, if you can make it work, then it works. but likely it won't work
Barbary LionOP
ok, thanks. So the "correct way" is to work with a cache and there is no way to fetch the data in one place and pass it down to the other functions?
no. the two functions run independently so you cant pass data between them
Barbary LionOP
Thanks, got it