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

Next.js 13中/api/user接口调用异常,Prisma创建用户失败

Next.js 13 API路由 + Prisma 创建用户失败问题修复

核心问题分析

  1. 后端API路由错误解析请求体:Next.js 13 App Router的POST函数接收的request是NextRequest类型,不能直接访问request.body,必须调用formData()或json()这类解析方法才能获取请求数据。你自定义的PostRequest接口不符合Next.js规范,导致request.body始终为undefined。
  2. 前端JSON提交拼写错误:代码里的JSON.stringfy是笔误,正确写法是JSON.stringify,且提交JSON时必须设置Content-Type: application/json请求头。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:05:00