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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 05:16:40