Next.js 13:Prisma ORM 数据获取问题 – 导航期间显示旧数据而不是更新后的数据

huangapple go评论75阅读模式
英文:

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 &quot;@prisma/client&quot;;
import { ListProvider } from &quot;~/context/list-context&quot;;
import { db } from &quot;~/lib/db&quot;; // 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[&quot;id&quot;]) {
  return await db.item.findMany({
    where: {
      parent_id: itemId,
    },
  });
}

export default async function ListLayout(params) {

  const items = await getChildItems(params.id);

  return (
    &lt;ListProvider listId={params.id} items={items}&gt;
      &lt;div&gt;{children}&lt;/div&gt;
    &lt;/ListProvider&gt;
  );
}

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 &quot;@prisma/client&quot;;
import { deletedAt } from &quot;../prismaMiddleware&quot;;

declare global {
  // eslint-disable-next-line no-var
  var cachedPrisma: PrismaClient;
}

let prisma: PrismaClient;
if (process.env.NODE_ENV === &quot;production&quot;) {
  prisma = new PrismaClient();
} else {
  if (!global.cachedPrisma) {
    global.cachedPrisma = new PrismaClient();
  }
  prisma = global.cachedPrisma;
}

prisma.$use(deletedAt);

export const db = prisma;

答案1

得分: 4

我相信在执行变异时,您应该使用 revalidatePathrevalidateTag,并记住重新验证不会立即发生,而是在您下次导航到重新验证的段落时发生。

英文:

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

huangapple
  • 本文由 发表于 2023年5月14日 04:14:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定