Careeroza
Dynamic Segments in Route Handlers
params in Handlers
app/api/products/[id]/route.ts — the second argument holds params, a Promise like in pages:
import { NextRequest } from 'next/server';
import { prisma } from '@/lib/prisma';
type Ctx = { params: Promise<{ id: string }> };
export async function GET(_req: NextRequest, { params }: Ctx) {
const { id } = await params;
const product = await prisma.product.findUnique({ where: { id: Number(id) } });
if (!product) return Response.json({ error: 'Product ' + id + ' not found' }, { status: 404 });
return Response.json(product);
}
export async function PATCH(req: NextRequest, { params }: Ctx) {
const { id } = await params;
const data = (await req.json()) as { price?: number; stock?: number };
const product = await prisma.product.update({ where: { id: Number(id) }, data });
return Response.json(product);
}
export async function DELETE(_req: NextRequest, { params }: Ctx) {
const { id } = await params;
await prisma.product.delete({ where: { id: Number(id) } });
return new Response(null, { status: 204 });
}Tip: Next.js also generates a RouteContext<'/api/products/[id]'> helper type for the second argument.
Requests
Example
curl localhost:3000/api/products/1
curl -X PATCH localhost:3000/api/products/1 -H "Content-Type: application/json" -d '{"stock":80}'
curl -i -X DELETE localhost:3000/api/products/1
curl -i localhost:3000/api/products/999Example output
{"id":1,"name":"Redmi Note 14","price":17999,"stock":120}
{"id":1,"name":"Redmi Note 14","price":17999,"stock":80}
HTTP/1.1 204 No Content
HTTP/1.1 404 Not Found
{"error":"Product 999 not found"}