0

this is my layout:

export default async function ClientLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <>
            <Header />
            <main>{children}</main>
            <Footer />
        </>
    );
}
export default async function Header() {
    const departments = await fetchDepartments();

    return (
        <header className={styles.navbar}>
            <nav className={`${styles.container} container`}>
                <Link href={"/"} className={styles.logo}>
                    <Image src={logo} priority={true} alt="logo" />
                </Link>
                <DepartmentsSelectContainer />
                <Links />
                <div className={styles.bookingBtn}>
                    <Link className={`btn yellow sm`} href={"/contacts"}>
                        Запис на прийом
                    </Link>
                </div>
            </nav>
        </header>
    );
}
export default async function Footer() {
    const departments = await fetchDepartments();

    return <div>currently empty</div>;
}

and my request function:

export async function fetchDepartments() {
    const first = Date.now();
    const data = await fetch(`${basicUrl}/departments`);
    const second = Date.now();
    console.log(second - first);
    const parsedData = await data.json();
    console.log("parsedData", parsedData);

    return parsedData;
}

so my problem is that my request isn't cached and it is executed 2 times. I also tried checking in my API if it really duplicates and it is.

How do i fix this, so Request Memoization cache data and the follovig requests will use cached data?

1 Answer 1

0

The reason you see two requests is because you are calling fetchDepartments() inside both Header and Footer. Each server component runs independently, so the fetch is executed twice.

A simple solution is to fetch the data once in your layout and pass it down as props:

export default async function ClientLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const departments = await fetchDepartments();

  return (
    <>
      <Header departments={departments} />
      <main>{children}</main>
      <Footer departments={departments} />
    </>
  );
}

Then in your components you use the params like this:

export default function Header({ departments }) {
  return (
    <header>
      {/* use departments here */}
    </header>
  );
}

export default function Footer({ departments }) {
  return <footer>{/* use departments here */}</footer>;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, this is valid solution to how to make my code work and I considered this solution. But using Request Memoization makes code much more readable and reusable and as i stated in my question Request Memoization somehow doesn't work and i want to make it work. Here is link to docs how it should work if you are interested: nextjs.org/docs/app/guides/caching#request-memoization
You are right, I think the reason your request is executed twice is that each Server Component (Header and Footer) has its own render scope. Request Memoization in Next.js only works within the same render pass, so calling fetchDepartments() in separate components will trigger separate requests. I think you can use force-cache as a header in the function to force the function to use the cache. const data = await fetch(${basicUrl}/departments, { cache: 'force-cache' }); If you want all the component functions to use the cache you can use "use cache" above everything
In the end i decided to use Data Cache instead of Request Memoization, so now it works as i wanted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.