使用Next.js API路由结合Prisma无法删除数据库条目
问题原因
```return (<Link>标签是Next.js用于客户端导航的组件,点击它会发起**GET请求**跳转到目标URL,但你的API路由仅实现了`DELETE`方法,因此点击后只会跳转到API地址,不会执行删除逻辑。 # 解决方案 ## 方案一:使用表单提交(App Router推荐方式) Next.js 13 App Router支持通过表单的`action`和`method`属性直接调用API路由的对应方法,无需手动处理请求: ```jsx // 替换原来的Link组件 <form action={`/api/todo/${id}`} method="POST" > {/* Next.js通过这个隐藏input指定请求方法为DELETE */} <input type="hidden" name="_method" value="DELETE" /> <button type="submit" className="bg-red-400 hover:bg-red-600 p-1 text-3xl rounded-xl"> <MdDelete /> )
同时修改API路由,兼容表单的_method参数(浏览器原生表单不支持DELETE方法,Next.js提供了这个兼容方式):
// /app/api/todo/[id]/route.ts import { prisma } from "@/lib/database"; import { NextResponse } from "next/server"; export async function POST( req: Request, { params }: { params: { id: string } } ) { const formData = await req.formData(); const method = formData.get("_method") as string; if (method === "DELETE") { try { await prisma.todo.delete({ where: { id: params.id }, }); // 删除成功后重定向到Todo列表页 return NextResponse.redirect(new URL("/todo", req.url)); } catch (error) { return NextResponse.json({ message: "删除失败,任务不存在" }, { status: 404 }); } } return NextResponse.json({ message: "不支持的请求方法" }, { status: 400 }); } // 保留原DELETE方法,供其他方式调用 export async function DELETE( req: Request, { params }: { params: { id: string } } ) { try { await prisma.todo.delete({ where: { id: params.id }, }); return NextResponse.json({ message: "删除成功" }); } catch (error) { return NextResponse.json({ message: "删除失败,任务不存在" }, { status: 404 }); } }
方案二:使用fetch发起DELETE请求
给删除按钮添加点击事件,手动调用API的DELETE方法,适合需要在客户端处理状态更新的场景:
import { MdDelete } from "react-icons/md"; import { useRouter } from "next/navigation"; export default function TodoItem({ id }: { id: string }) { const router = useRouter(); const handleDelete = async () => { if (confirm("确定要删除这个任务吗?")) { try { const res = await fetch(`/api/todo/${id}`, { method: "DELETE" }); if (res.ok) { // 删除成功后刷新页面或更新本地状态 router.refresh(); } else { alert("删除失败,请重试"); } } catch (error) { alert("网络错误,请检查连接"); } } }; return ( <button onClick={handleDelete} className="bg-red-400 hover:bg-red-600 p-1 text-3xl rounded-xl" > <MdDelete /> </button> ); }
这种方式不需要修改原API路由,保持你原来的DELETE方法即可。
额外提示
- 无论哪种方案,都建议添加错误处理,比如处理Prisma抛出的
NotFoundError(当要删除的Todo不存在时),返回合适的状态码和提示信息。 - 如果使用客户端状态管理(比如React Context、Zustand),删除成功后可以直接更新本地状态,无需刷新页面,提升用户体验。
内容的提问来源于stack exchange,提问作者GN Vageesh
相关产品推荐
相关产品推荐

