求助: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
相关产品推荐
相关产品推荐

