Reputation: 389
Consider the following server side component that's part of some page (page.js) in the app directory, representing a person:
export default async function Person({ params }) {
const person = await getPerson(params.id);
return (
<h1> {person.name} </h1>
<p> {person.bio} </p>
)
}
Obviously, the intent here is to dynamically render new pages, with the idea being that the URL looks something like /person/{id}
, where ID is the unique ID of each person.
The issue I'm running into is that I need to set metadata for the page. For example, I want the title to be person.name
, and the description to be person.description
. From what I'm reading, the only way to do that in NextJS 13 with the app directory is to use generateMetadata
, which would look something like this:
export async function generateMetadata({ params }) {
const person = await getPerson(params.id);
return {
title: person.name,
description: person.description
}
}
I'm sure you can see the issue now: I need to make the exact same request (getPerson
) twice in the same page. From what I've seen, there isn't a way to pass data between generateMetadata
and the page component.
The <Head>
component from next/head
seems like the ideal solution, but it doesn't appear to work in the app directory with NextJS 13.
Am I missing something really obvious here? Or is this an absolutely massive oversight by Next's devs?
Upvotes: 24
Views: 6626
Reputation: 759
In NextJS data requests are cached unless you opt out according to official doc on the data cache
React extends the fetch API to automatically memoize requests that have the same URL and options. This means you can call a fetch function for the same data in multiple places in a React component tree while only executing it once.
Upvotes: 0
Reputation: 2853
If the function you're calling is internally calling fetch it is automatically deduplicated by Next.js as can be read in the official documentation here.
Should you be directly calling a database or using a fetch alternative (like axios) as explained you can use Reacts new cache()
function to deduplicate calls to logic that does not automatically get deduped by Next.js. More can be found in the official documentation here
import { cache } from 'react'
export const getPerson = cache(async () => {
// your logic ...
});
Although the getPerson()
function is called twice, inside the page and metadata generator, only one call will be made. This is because the function is wrapped in cache()
, so the second request can reuse the result from the first request.
Upvotes: 19