For this question I have created the following demo Next.js application using the App directory:
RootLayout
in app/layout.tsx
.Layout
in a route group app/(app)/layout.tsx
. This layout contains <nav />
.app/(app)/a/page.tsx
and app/(app)/b/page.tsx
.getCurrentTime()
(defined on app/functions.ts
) and then display the render time.I want each navigation to a page to cause a re-render and run getCurrentTime()
again, but I couldn't make the pages not cache. I've tried adding both export const revalidate = 0
and export const dynamic = "force-dynamic"
(docs), but couldn't make it work.
I’m sure it’s pretty basic, but I still couldn’t get the hang of it.
View on StackBlitz
According to the Next.js docs, seems like the mechanism responsible for caching pages on the client is the Router Cache and its purpose is to reduce server requests on navigation (source).
The documentation says: (source)
Opting Out ‒ It's not possible to opt out of the Router Cache. However, you can invalidate it by calling
router.refresh
,revalidatePath
, orrevalidateTag
. This will clear the cache and make a new request to the server, ensuring the latest data is shown.
Since revalidatePath
and revalidateTag
can only be used in a server action, I ended with this creating a pseudo client component that will refresh the page on any navigation to it.
It's not the prettiest solution but it works.
"use client";
import { useRouter } from "next/navigation";
import { useEffect, useRef } from "react";
const Refresh = () => {
const router = useRouter();
const pathname = usePathname();
const InitialPathname = useRef(pathname);
useEffect(() => {
if (InitialPathname.current === pathname) return;
router.refresh();
}, [router, pathname]);
return null;
};
export default Refresh;
Expanding on Iftach's answer a bit, I was able to make a refresh button as follows:
"use client";
import { useRouter } from "next/navigation";
import { Button } from "react-bootstrap";
const ButtonRefresher = () => {
const router = useRouter();
return (<Button onClick={router.refresh}>Refresh</Button>);
};
export default ButtonRefresher;
On my page, I have a server component that uses fetch to grab some data from a url. The fetch looks like this: await fetch(url, { cache: "no-cache"});
. The no-cache
option forces NextJS to fetch the data on the url every time the component is re-rendered.
Including this button on the page causes the whole page to be re-rendered on the server side and sent to the client which includes fetching the data and re-rendering how the data is displayed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With