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

求助:Next.js+Prisma如何动态获取catSlug参数并实现数据查询

解决Next.js中动态路径参数传递到Prisma查询的问题

在Next.js搭配Prisma开发时,需要从URL路径参数(如/cities或/experiences中的cities/experiences)动态获取catSlug并用于Prisma查询条件,以下是针对性的修正方案:

一、修改API路由,动态接收catSlug参数

当前API路由中catSlug为硬编码值,需改为从请求中动态获取。这里采用查询参数传递的方式适配现有逻辑:

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

export const GET = async (req: NextRequest) => {
  const { searchParams } = new URL(req.url);
  const page = searchParams.get("page");
  const catSlug = searchParams.get("catSlug");

  // 校验catSlug参数是否存在
  if (!catSlug) {
    return new NextResponse(JSON.stringify({ message: "catSlug参数缺失", status: 400 }));
  }

  const POST_PER_PAGE = 4;

  const query = {
    where: { catSlug }, // 替换硬编码为动态参数
    take: POST_PER_PAGE,
    skip: POST_PER_PAGE * (Number(page) - 1),
  };

  try {
    // 注意:count查询需同步带上catSlug条件,避免统计全量文章
    const [posts, count] = await prisma.$transaction([
      prisma.post.findMany(query),
      prisma.post.count({ where: { catSlug } }),
    ]);

    return new NextResponse(JSON.stringify({ posts, count, status: 200 }));
  } catch (error) {
    console.error(error);
    return new NextResponse(JSON.stringify({ message: "Something went wrong!", status: 500 }));
  }
};

二、修改动态分类页面,传递catSlug给API

当前页面调用getPaginatedPosts时未传递分类参数,需修改工具函数及页面逻辑:

1. 更新getPaginatedPosts工具函数(@/helpers/utils)

export async function getPaginatedPosts(page: number, catSlug: string) {
  const res = await fetch(`/api/posts?page=${page}&catSlug=${catSlug}`, { cache: "no-store" });

  if (!res.ok) {
    throw new Error('Failed to fetch posts');
  }

  return res.json();
}

2. 调整动态分类页面代码

import { Container, Pagination, PostList } from "@/components";
import prisma from "@/helpers/connect";
import { getPaginatedPosts } from "@/helpers/utils";
import { Category, Post } from "@/types";
import { notFound } from "next/navigation";

export const generateStaticParams = async () => {
  try {
    const categories = await prisma.category.findMany({
      select: { slug: true },
    });

    return categories.map((category) => ({
      category: category.slug,
    }));
  } catch (error) {
    console.log(error);
    throw new Error("error generating params");
  }
};

export default async function CategoryPage({
  params,
  searchParams,
}: {
  params: { category: string };
  searchParams: { page: number };
}) {
  const category = await prisma.category.findUnique({
    where: {
      slug: params.category,
    },
  });

  if (!category) notFound();

  const page = Number(searchParams.page) || 1;
  // 传递路径参数中的category作为catSlug给API
  const { posts, count }: { posts: Post[], count: number } = await getPaginatedPosts(page, params.category);

  // 计算分页状态
  const POST_PER_PAGE = 4;
  const hasPrev = page > 1;
  const hasNext = page < Math.ceil(count / POST_PER_PAGE);

  return (
    <Container>
      <div className="mb-10">
        <h1 className="text-4xl mb-1 font-semibold">{category?.title}</h1>
        <p className="text-lg text-neutral-600">{category?.description}</p>
      </div>

      <div className="mb-24">
        <PostList posts={posts} />
      </div>

      <Pagination page={page} hasPrev={hasPrev} hasNext={hasNext} />
    </Container>
  );
}

替代方案:使用RESTful动态API路由

若希望API路径更规范(如/api/posts/cities?page=1),可创建动态API路由app/api/posts/[catSlug]/route.ts,代码如下:

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

export const GET = async (req: NextRequest, { params }: { params: { catSlug: string } }) => {
  const { searchParams } = new URL(req.url);
  const page = searchParams.get("page");
  const catSlug = params.catSlug;

  const POST_PER_PAGE = 4;

  const query = {
    where: { catSlug },
    take: POST_PER_PAGE,
    skip: POST_PER_PAGE * (Number(page) - 1),
  };

  try {
    const [posts, count] = await prisma.$transaction([
      prisma.post.findMany(query),
      prisma.post.count({ where: { catSlug } }),
    ]);

    return new NextResponse(JSON.stringify({ posts, count, status: 200 }));
  } catch (error) {
    console.error(error);
    return new NextResponse(JSON.stringify({ message: "Something went wrong!", status: 500 }));
  }
};

对应的getPaginatedPosts函数修改为:

export async function getPaginatedPosts(page: number, catSlug: string) {
  const res = await fetch(`/api/posts/${catSlug}?page=${page}`, { cache: "no-store" });

  if (!res.ok) {
    throw new Error('Failed to fetch posts');
  }

  return res.json();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:47:14