Clarification NextJS Caching Revalidation

Hi! i have the function:
const getData = unstable_cache(
async () => {
const usersData = await db.select().from(users);
return { users: usersData };
},
["users"],
{
revalidate: false
},
);

export default async function Page() {
const data = await getData();

return (
<main className="container mx-auto p-4">
<h1 className="mb-6 text-3xl font-bold">User and Course Management</h1>
<CreateCoursePopup />
<UsersTable users={data.users} />
</main>
);
}
const getData = unstable_cache(
async () => {
const usersData = await db.select().from(users);
return { users: usersData };
},
["users"],
{
revalidate: false
},
);

export default async function Page() {
const data = await getData();

return (
<main className="container mx-auto p-4">
<h1 className="mb-6 text-3xl font-bold">User and Course Management</h1>
<CreateCoursePopup />
<UsersTable users={data.users} />
</main>
);
}
and I have the update function:
"use server";

import { adminAction } from "@/server/api/actions";
import { updateUserInput } from "@/validators/users";
import { revalidatePath, revalidateTag } from "next/cache";
import { users } from "@/server/db/schema";
import { db } from "@/server/db";
import { eq } from "drizzle-orm";
import { z } from "zod";

export const updateUserAction = adminAction
.schema(updateUserInput)
.action(async ({ parsedInput }) => {
await db.update(users).set(parsedInput).where(eq(users.id, parsedInput.id));
revalidateTag("users");
});

export const deleteUserAction = adminAction
.schema(z.object({ id: z.string() }))
.action(async ({ parsedInput }) => {
await db.delete(users).where(eq(users.id, parsedInput.id));
revalidateTag("users");
});
"use server";

import { adminAction } from "@/server/api/actions";
import { updateUserInput } from "@/validators/users";
import { revalidatePath, revalidateTag } from "next/cache";
import { users } from "@/server/db/schema";
import { db } from "@/server/db";
import { eq } from "drizzle-orm";
import { z } from "zod";

export const updateUserAction = adminAction
.schema(updateUserInput)
.action(async ({ parsedInput }) => {
await db.update(users).set(parsedInput).where(eq(users.id, parsedInput.id));
revalidateTag("users");
});

export const deleteUserAction = adminAction
.schema(z.object({ id: z.string() }))
.action(async ({ parsedInput }) => {
await db.delete(users).where(eq(users.id, parsedInput.id));
revalidateTag("users");
});
and the data on the page is not revalidatnig when I call the functions, I've tried revalidatePath, same issue. I know the function works because when I Crtl + Shift + R the data is correct. Any insights into why?
7 Replies
Ani
AniOP5mo ago
nextjs 15 and also the page is showing a static icon even tho the page is clearly dynamic what am i missing? i'm also router.refresh() ing and it doesn't work same on build and dev with and without turbopack
Benfa
Benfa2mo ago
have you find out why? i'm having a similar problem
Ani
AniOP2mo ago
because giving unstable cache a key isn't the same as tagging it
const getData = unstable_cache(
async () => {
const usersData = await db.select().from(users);
return { users: usersData };
},
["users"],
{
revalidate: false,
tags: ["users"], // add this line here
},
);
const getData = unstable_cache(
async () => {
const usersData = await db.select().from(users);
return { users: usersData };
},
["users"],
{
revalidate: false,
tags: ["users"], // add this line here
},
);
you'd do something like that it isn't intutive at all but I guess dynamic IO should fix that problem
Benfa
Benfa2mo ago
it sill doesn't work for me, i eneded up exporting dynamic = "force-dynamic"
Ani
AniOP2mo ago
Hey this is prob because you're using httpBatchStreamLink as your link in trpc, this won't work because the response is sent as soon as the request is received, and then the response body is streamed without the headers httpBatchLink seems to be a good link for my app so I just changed over to it https://trpc.io/docs/client/links
Links Overview | tRPC
Links enable you to customize the flow of data between the tRPC Client and Server. A link should do only one thing, which can be either a self-contained modification to a tRPC operation (query, mutation, or subscription) or a side-effect based on the operation (such as logging).
Benfa
Benfa2mo ago
thank you very much for the response! but i ended up switching to tan stack start, it isn't perfect but i find it more explicit than next
Ani
AniOP4w ago
awesome!

Did you find this page helpful?