Issue/Confusion with caching + NextJS & SWR
Unanswered
Floh posted this in #help-forum
FlohOP
I have a component on my app which is fetching data using SWR and a route handler.
No matter what I do, the value will not re-validate, and always shows the cached value (unless I disable cache on browser).
You can see I tried a few tricks like adding timestamp to the URL, sending no-store header, and including the revalidation arguments to the SWR hook. None of which resolved the issue.
The requests are being sent properly, but it always returns the same value.
I guess my questions are:
- Which part of my app is responsible for the aggressive caching?
- How do I stop it?
Route handler:
Client component with SWR
No matter what I do, the value will not re-validate, and always shows the cached value (unless I disable cache on browser).
You can see I tried a few tricks like adding timestamp to the URL, sending no-store header, and including the revalidation arguments to the SWR hook. None of which resolved the issue.
The requests are being sent properly, but it always returns the same value.
I guess my questions are:
- Which part of my app is responsible for the aggressive caching?
- How do I stop it?
Route handler:
/api/posts/[id]/viewsimport { createClient } from "@supabase/supabase-js";
import { NextRequest, NextResponse } from "next/server";
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const id = params.id;
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
// do the fetching
const { data, error } = await supabase
.from("posts")
.select("views")
.eq("id", id)
.single();
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
}Client component with SWR
"use client";
import { Loader2 } from "lucide-react";
import useSWR from "swr";
export default function ViewCount(props: { id: string }) {
const fetcher = async (url: string) => {
const res = await fetch(`${url}?timestamp=${new Date().getTime()}`, {
cache: "no-store", // Ensure no caching by fetch API
});
if (!res.ok) throw new Error("Network response was not ok");
return res.json();
};
const { data, error, isLoading, isValidating } = useSWR(
`/api/posts/${props.id}/views`,
fetcher,
{
revalidateOnFocus: true,
revalidateOnReconnect: true,
refreshInterval: 30000,
}
);
if (error) {
console.error(error);
return <div>Error</div>;
}
return (
<div>
<span className="flex gap-2">
<span>Views:</span>
{isLoading || isValidating ? (
<Loader2 size={20} className="animate-spin" />
) : (
data?.views
)}
</span>
</div>
);
}1 Reply
FlohOP
Ok so I discovered that setting the revalidation frequency in the Route Handler resolved the issue.
Now my confusion still exists though.
What's the point of SWR having it's own validation and caching methods if it all just comes down to the Route Handler's revalidation frequency anyway?
What's the proper way to make them work together nicely? Do I just have to make sure the SWR revalidation occurs less often than the route handler revalidation time?
Now my confusion still exists though.
What's the point of SWR having it's own validation and caching methods if it all just comes down to the Route Handler's revalidation frequency anyway?
What's the proper way to make them work together nicely? Do I just have to make sure the SWR revalidation occurs less often than the route handler revalidation time?