英文:
Next.js 13: Data Fetching Issue with Prisma ORM - Old Data Displayed During Navigation Instead of Updated Data
问题
I am using Next.js 13 and Prisma ORM to fetch data within a server component and make it available to child components through a context. The route is structured as follows: /item/[id]
, and the id is utilized within the layout.tsx file to fetch data.
Upon the initial page load, data is fetched and made accessible to all child components through the context. However, I encounter an issue when modifying the data in the context (and updating it in the database via API calls). When navigating to a new page and then returning to the previous page, the old data is displayed from the initial load. The server-side function getChildItems
, which should execute each time the page loads, only runs on a page refresh, but not during back and forth navigation. I could use router.refresh()
from next/navigation
when a change is made, but I don't think this is optimal.
Since this is a server component, I can't use hooks like useEffect. It would be possible to fetch the data in a client component from the api, but I want to render the page on the server if possible.
Here is my layout.tsx:
import { Item } from "@prisma/client";
import { ListProvider } from "~/context/list-context";
import { db } from "~/lib/db"; // Prisma ORM database connection
// This should run every time when navigating to /items/[id] but currently runs only on page refresh
async function getChildItems(itemId: Item["id"]) {
return await db.item.findMany({
where: {
parent_id: itemId,
},
});
}
export default async function ListLayout(params) {
const items = await getChildItems(params.id);
return (
<ListProvider listId={params.id} items={items}>
<div>{children}</div>
</ListProvider>
);
}
I am sure Next.js is caching this page, but I have not found a way to invalidate the cache for a server component that actually works.
Thanks for your help in advance!
Edit: Here is the db code, if necessary:
import { PrismaClient } from "@prisma/client";
import { deletedAt } from "../prismaMiddleware";
declare global {
// eslint-disable-next-line no-var
var cachedPrisma: PrismaClient;
}
let prisma: PrismaClient;
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient();
} else {
if (!global.cachedPrisma) {
global.cachedPrisma = new PrismaClient();
}
prisma = global.cachedPrisma;
}
prisma.$use(deletedAt);
export const db = prisma;
英文:
I am using Next.js 13 and Prisma ORM to fetch data within a server component and make it available to child components through a context. The route is structured as follows: /item/[id]
, and the id is utilized within the layout.tsx file to fetch data.
Upon the initial page load, data is fetched and made accessible to all child components through the context. However, I encounter an issue when modifying the data in the context (and updating it in the database via API calls). When navigating to a new page and then returning to the previous page, the old data is displayed from the initial load. The server-side function getChildItems
, which should execute each time the page loads, only runs on a page refresh, but not during back and forth navigation. I could use router.refresh()
from next/navigation
when a change is made, but I don't think this is optimal.
Since this is a server component, I can't use hooks like useEffect. It would be possible to fetch the data in a client component from the api, but I want to render the page on the server if possible.
Here is my layout.tsx:
import { Item } from "@prisma/client";
import { ListProvider } from "~/context/list-context";
import { db } from "~/lib/db"; // Prisma ORM database connection
// This should run every time when navigating to /items/[id] but currently runs only on page refresh
async function getChildItems(itemId: Item["id"]) {
return await db.item.findMany({
where: {
parent_id: itemId,
},
});
}
export default async function ListLayout(params) {
const items = await getChildItems(params.id);
return (
<ListProvider listId={params.id} items={items}>
<div>{children}</div>
</ListProvider>
);
}
I am sure Next.js is caching this page, but I have not found a way to invalidate the cache for a server component that actually works.
Thanks for your help in advance!
Edit: Here is the db code, if necessary:
import { PrismaClient } from "@prisma/client";
import { deletedAt } from "../prismaMiddleware";
declare global {
// eslint-disable-next-line no-var
var cachedPrisma: PrismaClient;
}
let prisma: PrismaClient;
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient();
} else {
if (!global.cachedPrisma) {
global.cachedPrisma = new PrismaClient();
}
prisma = global.cachedPrisma;
}
prisma.$use(deletedAt);
export const db = prisma;
答案1
得分: 4
我相信在执行变异时,您应该使用 revalidatePath
或 revalidateTag
,并记住重新验证不会立即发生,而是在您下次导航到重新验证的段落时发生。
英文:
I believe you should use revalidatePath
or revalidateTag
when you perform the mutation, and remember that the revalidation doesn't happen right away, but at your next navigation to the revalidated segment.
答案2
得分: 3
你需要从page.tsx
文件中导出一个常量以重新验证。
export const revalidate = 1; //每一秒重新验证一次 -- 需要重新加载页面
英文:
You need to export a constant from the page.tsx
to revalidate.
export const revalidate = 1; //revalidates every one second -- requires page reload
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论