Next.js 13中/api/user接口调用异常,Prisma创建用户失败
Next.js 13 API路由 + Prisma 创建用户失败问题修复
核心问题分析
- 后端API路由错误解析请求体:Next.js 13 App Router的
POST函数接收的request是NextRequest类型,不能直接访问request.body,必须调用formData()或json()这类解析方法才能获取请求数据。你自定义的PostRequest接口不符合Next.js规范,导致request.body始终为undefined。 - 前端JSON提交拼写错误:代码里的
JSON.stringfy是笔误,正确写法是JSON.stringify,且提交JSON时必须设置Content-Type: application/json请求头。 - API返回格式错误:原代码直接返回
prisma.user.findFirst()(一个Promise),没有封装成Next.js要求的响应格式。
解决方案
第一步:修复后端API路由(@/app/api/user/route.ts)
替换为以下代码,使用Next.js官方类型并正确解析请求体:
import { PrismaClient } from "@prisma/client"; import { NextRequest, NextResponse } from "next/server"; const prisma = new PrismaClient(); export async function POST(request: NextRequest) { try { // 二选一:根据前端提交方式选择解析方法 // 方式1:解析FormData const formData = await request.formData(); const name = formData.get("name") as string; const email = formData.get("email") as string; const password = formData.get("password") as string; // 方式2:解析JSON(若前端用JSON提交,替换上面的代码为下面这行) // const { name, email, password } = await request.json(); // 验证必填字段 if (!name || !email || !password) { return NextResponse.json({ error: "缺少必填字段" }, { status: 400 }); } const newUser = await prisma.user.create({ data: { name, email, password }, }); return NextResponse.json(newUser, { status: 201 }); } catch (error) { console.error(error); return NextResponse.json({ error: "创建用户失败" }, { status: 500 }); } finally { await prisma.$disconnect(); } }
第二步:修复前端提交代码
情况1:继续使用FormData提交(@/app/page.tsx)
原代码逻辑正确,可添加日志验证数据:
"use client"; import { FormEvent } from "react"; export default function Home() { async function handlePost(event: FormEvent<HTMLFormElement>) { event.preventDefault(); const formData = new FormData(event.currentTarget); // 验证FormData是否获取到值 console.log("name:", formData.get("name")); console.log("email:", formData.get("email")); try { const response = await fetch("/api/user", { method: "POST", body: formData, // FormData会自动设置正确的Content-Type }); const data = await response.json(); console.log("创建成功:", data); } catch (error) { console.error("请求失败:", error); } } return ( <form onSubmit={handlePost} className="flex flex-col gap-5 w-[300px] m-auto mt-[200px]" > <input type="text" name="name" id="name" required /> <input type="email" name="email" id="email" required /> <input type="password" name="password" id="password" required /> <button type="submit">Submit</button> </form> ); }
情况2:改用JSON提交
修复拼写错误并添加请求头:
"use client"; import { FormEvent } from "react"; export default function Home() { async function handlePost(event: FormEvent<HTMLFormElement>) { event.preventDefault(); const form = event.currentTarget; const formData = new FormData(form); const userData = { name: formData.get("name") as string, email: formData.get("email") as string, password: formData.get("password") as string, }; try { const response = await fetch("/api/user", { method: "POST", headers: { "Content-Type": "application/json", // 必须设置该请求头 }, body: JSON.stringify(userData), // 修复拼写错误:stringfy -> stringify }); const data = await response.json(); console.log("创建成功:", data); } catch (error) { console.error("请求失败:", error); } } return ( <form onSubmit={handlePost} className="flex flex-col gap-5 w-[300px] m-auto mt-[200px]" > <input type="text" name="name" id="name" required /> <input type="email" name="email" id="email" required /> <input type="password" name="password" id="password" required /> <button type="submit">Submit</button> </form> ); }
关键注意事项
- 后端必须匹配前端的提交类型选择解析方法:
request.formData()对应multipart/form-data,request.json()对应application/json。 - Prisma操作务必放在
try/catch中捕获错误,且在finally中断开连接(或使用全局Prisma实例的最佳实践)。 - 前端表单添加
required属性可提前在客户端做基础验证,减少无效请求。
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

