Search code examples
javascriptreactjsnext.jsfetch-apinext.js13

Next.JS fetch not memoizing in the same request


I have a simple set up, a Next.JS server side component which fetches a post and then displays the post. The page title needs to be set to the title of the post. I have to call my posts API endpoint twice: once in the generateMetadata and once in the component itself.

According to Next.JS's documentation, fetch requests are memoized during the entire request. When testing locally, for me, this is not the case, I can see in my API logs that the API endpoint is being hit twice. What is the correct way to get the fetch memoization to work? Below is my (simplified) component code:

// posts/[slug]/page.tsx

import {Metadata} from "next";
import {PostResponse} from "@/service/model/api";

export async function generateMetadata(props: PostPageProps): Promise<Metadata> {
    const response = await fetch(`${process.env.BASE_URL}/api/posts/slug?slug=${props.params.slug}`, {
        method: "GET",
        headers: {
            "Authorization": `Bearer ${process.env.API_KEY}`
        },
    });

    const posts: PostResponse = await response.json();

    return {
        title: posts.posts[0].title
    }
}

export default async function PostPage(props: PostPageProps) {
    const response = await fetch(`${process.env.BASE_URL}/api/posts/slug?slug=${props.params.slug}`, {
        method: "GET",
        headers: {
            "Authorization": `Bearer ${process.env.API_KEY}`
        },
    });
    const posts: PostResponse = await response.json();

    return (<div>
               <p>{posts.posts[0].title}</p>
           </div>);

}

export interface PostPageProps {
    params: PostPageParams;
}

interface PostPageParams {
    slug: string;
    text?: string;
}


Solution

  • Okay, I've figured it out.

    As it turns out, Next.JS/React does not do the memoization of the fetch() calls when running in development mode / locally.

    Once I make a production build and use that one, the memoization is working correctly and only one request hits my API endpoint.

    As to why... I have no idea, but it should be documented better in the Next.JS documentation.