You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js + Prisma 博客文章浏览量不更新问题求助

问题:Next.js + Prisma博客文章浏览量无法递增

我正在使用Next.js和Prisma开发一个博客应用,在根据ID展示文章的详情页中,希望每次页面被获取时递增浏览量,但浏览量完全没有变化。

我尝试过在递增浏览量前获取文章、递增后获取文章,甚至使用带select的update语句一步完成获取与递增,但这些方案都无效。我没有在每次请求时创建新的Prisma Client实例,数据库连接稳定,更新浏览量时也没有抛出任何错误。


相关代码

page.tsx

import BackButton from "@/components/BackButton";
import Badge from "@/components/Badge";
import DeleteButton from "@/components/DeleteButton";
import Like from "@/components/Like";
import Views from "@/components/Views";
import { Tag } from "@prisma/client";
import { Pencil } from "lucide-react";
import Link from "next/link";

interface Props {
  params: {
    id: string;
  };
}

interface Post {
  id: string;
  title: string;
  content: string;
  tag: Tag;
  views: number;
  likes: number;
}

const getPost = async ({ params }: Props): Promise<Post> => {
  const res = await fetch(`http://localhost:3000/api/posts/${params.id}`, {
    cache: "no-store",
  });
  return res.json();
};

const DetailPage = async ({ params }: Props) => {
  const post = await getPost({ params });
  return (
    <div className="flex flex-col gap-4 max-w-lg">
      <BackButton href="/posts" />
      <div className="flex justify-between gap-1 items-baseline max-w-sm">
        <h1 className="text-3xl font-bold">{post.title}</h1>
        {post.tag && <Badge tag={post.tag.name} />}
      </div>
      <div className="flex justify-start gap-4 items-baseline max-w-sm">
        <div className="flex items-center gap-4">
          <Link href={`/posts/edit/${post.id}`} className="btn btn-warning">
            <Pencil /> Edit
          </Link>
          <DeleteButton params={params} />
        </div>
        <Views views={post.views} />
        <Like likes={post.likes} />
      </div>
      <p className="max-w-md">{post.content}</p>
    </div>
  );
};
export default DetailPage;

route.tsx

import prisma from "@/prisma/client";
import { NextRequest, NextResponse } from "next/server";

interface Props {
  params: {
    id: string;
  };
}

export async function GET(req: NextRequest, { params }: Props) {
  try {
    const post = await prisma.post.update({
      where: {
        id: params.id,
      },
      data: {
        views: {
          increment: 1,
        },
      },
      select: {
        id: true,
        title: true,
        content: true,
        tag: true,
        views: true,
        likes: true,
      },
    });
    return NextResponse.json(post, { status: 200 });
  } catch (error) {
    return NextResponse.json(
      { message: "Could not fecth the post" },
      { status: 500 }
    );
  }
}

views.tsx

import { Eye } from "lucide-react";

interface Props {
  views: number;
}

const Views = ({ views }: Props) => {
  console.log("****Views****: ", views);
  return (
    <div className="flex gap-1 items-center">
      <Eye size={23} />
      <span className="font-bold text-sm">{views}</span>
    </div>
  );
};
export default Views;

prisma.schema.ts

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

model Tag {
  id   String @id @default(cuid()) @map("_id")
  name String
  post Post[]
}

model Post {
  id        String   @id @default(cuid()) @map("_id")
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title     String
  content   String
  views     Int      @default(0)
  likes     Int      @default(0)
  tag       Tag?     @relation(fields: [tagId], references: [id])
  tagId     String
}

问题分析与解决方案

可能的原因

  1. ID不匹配:请求传递的文章ID与数据库中存储的_id(映射自模型的id)不一致,导致Prisma无法找到目标文档,update操作无实际效果且不会抛出错误(MongoDB特性)。
  2. 页面缓存:Next.js App Router默认会缓存服务器组件数据,即使fetch设置了cache: "no-store",仍可能存在缓存导致旧数据重复展示。
  3. 未捕获的静默错误:可能存在权限、字段不存在等MongoDB层面的静默问题,未被当前代码捕获。

修复步骤

  1. 验证ID一致性

    • 在DetailPage中添加console.log(params.id),在route.tsx的GET方法中添加console.log(params.id),确认传递的ID与Prisma Studio中显示的文章_id完全一致。
  2. 增强错误处理与日志
    修改route.tsx的GET方法,添加文档不存在判断与错误日志:

    export async function GET(req: NextRequest, { params }: Props) {
      try {
        const post = await prisma.post.update({
          where: {
            id: params.id,
          },
          data: {
            views: {
              increment: 1,
            },
          },
          select: {
            id: true,
            title: true,
            content: true,
            tag: true,
            views: true,
            likes: true,
          },
        });
    
        // 检查是否找到并更新了文章
        if (!post) {
          return NextResponse.json({ message: "Post not found" }, { status: 404 });
        }
    
        return NextResponse.json(post, { status: 200 });
      } catch (error) {
        // 打印详细错误信息
        console.error("Update error:", error);
        return NextResponse.json(
          { message: "Could not fetch the post", error: (error as Error).message },
          { status: 500 }
        );
      }
    }
    
  3. 强制禁用页面缓存
    在page.tsx顶部添加以下代码,确保服务器组件每次请求都重新渲染:

    export const revalidate = 0;
    
  4. 验证数据库操作

    • 使用Prisma Studio直接修改某篇文章的views字段,确认数据库可以正常更新。
    • 尝试通过Prisma CLI执行手动更新命令,验证操作有效性:
      npx prisma studio
      # 或在脚本中执行
      await prisma.post.update({ where: { id: "你的文章ID" }, data: { views: { increment: 1 } } })
      
  5. 检查Prisma版本
    确保使用的Prisma版本支持MongoDB的increment操作,建议升级到最新稳定版:

    npm update prisma @prisma/client
    

内容的提问来源于stack exchange,提问作者Morteza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:55:56