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

NextJS注册页面提交报错:Mongoose必填字段验证失败

注册页面提交触发Mongoose必填字段验证失败问题解决

问题描述

我是一名中级JavaScript开发者,这是我的第二个NextJS项目。当前注册页面存在以下问题:

  • 使用ThunderClient发送POST请求时无任何错误,数据能正常存入MongoDB
  • 通过注册页面提交表单时触发MongooseValidatorError,提示:用户验证失败:password:路径password为必填项,email:路径email为必填项,name:路径name为必填项
  • 日志显示字段值均为undefined,移除Mongoose模型中必填限制后,会向MongoDB插入空数据

相关代码

注册页面组件代码

import React from "react";
import { useState } from "react";
import Link from "next/link";

const Signup = () => {
  const [name, setName] = useState()
  const [email, setEmail] = useState()
  const [password, setPassword] = useState()
  const handleChange = (e) => {
    if(e.target.name == 'name'){
      setName(e.target.value);
    } 
    else if(e.target.name == 'email'){
      setEmail(e.target.value);
    } 
    else if(e.target.name == 'password'){
      setPassword(e.target.value);
    }
  };
  const handleSubmit = async (e) => {
    e.preventDefault()
    const data = { name, email, password }
    let res = await fetch('http://localhost:3000/api/signup', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data),
      
    });
    let response = await res.json();
    console.log(response);
   
    setName('')
    setEmail('')
    setPassword('')
  };

  return (
    <div className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 flex flex-col">
      <form onSubmit={handleSubmit} className='mt-8 space-y-10' method="POST">
        <div className="mb-4">
          <label
            className="block text-grey-darker text-sm font-bold mb-2"
            htmlFor="name"
          >
            Name
          </label>
          <input
            value={name}
            onChange={handleChange}
            required
            className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
            id="name"
            type="text"
            placeholder="name"
          />
        </div>
        <div className="mb-4">
          <label
            className="block text-grey-darker text-sm font-bold mb-2"
            htmlFor="email"
          >
            Email
          </label>
          <input
            value={email}
            onChange={handleChange}
            required
            className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
            id="email"
            type="email"
            placeholder="email"
          />
        </div>
        <div className="mb-6">
          <label
            className="block text-grey-darker text-sm font-bold mb-2"
            htmlFor="password"
          >
            Password
          </label>
          <input
            value={password}
            onChange={handleChange}
            required
            className="shadow appearance-none border border-red rounded w-full py-2 px-3 text-grey-darker mb-3"
            id="password"
            type="password"
            placeholder="Password"
          />
          <p className="text-red text-xs italic">Please choose a password.</p>
        </div>
        <div className="flex items-center justify-between">
          <button
            className="bg-blue hover:bg-blue-dark text-black font-bold py-2 px-4 rounded"
            type="submit"
          >
            Sign In
          </button>
          <a
            className="inline-block align-baseline font-bold text-sm text-blue hover:text-blue-darker"
            href="/forgot"
          >
            Forgot Password?
          </a>
        </div>
      </form>
    </div>
  );
};
export default Signup;

Mongoose模型文件

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema(
    {
        name: {type: String, required: true},
        email: {type: String, required: true, unique: true},
        password: {type: String, required: true},
    }, {timestamps: true}
);
mongoose.models = {}
export default mongoose.model("User", UserSchema);

API代码

import connectDb from "../../middleware/mongoose"
import User from "../../models/User"
const handler = async (req, res)=> {
    if(req.method == 'POST'){
        let u = new User(req.body)
       await u.save()
    res.status(200).json({success: "success"})
}
    else{
        res.status(400).json({error: "this method is not allowed"})
    }
    
  }
  export default connectDb(handler);

日志错误信息

{
    properties: [Object],
    kind: 'required',
    path: 'email',
    value: undefined,
    reason: undefined,
    [Symbol(mongoose:validatorError)]: true
}

问题根源

注册组件中的所有<input>标签都缺少name属性,而handleChange函数是通过判断e.target.name来更新对应state的。因为没有name属性,e.target.name为空字符串,导致state从未被正确更新,最终提交给后端的data对象中name、email、password均为undefined,触发Mongoose的必填字段验证错误。

ThunderClient请求正常是因为手动构造了包含正确字段的JSON数据,不受前端表单的name属性影响。

解决方案

给每个<input>标签添加对应的name属性,确保与handleChange中的判断值一致:

修改后的注册组件关键部分

// Name输入框
<input
  value={name}
  onChange={handleChange}
  required
  className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
  id="name"
  name="name" // 新增name属性
  type="text"
  placeholder="name"
/>

// Email输入框
<input
  value={email}
  onChange={handleChange}
  required
  className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
  id="email"
  name="email" // 新增name属性
  type="email"
  placeholder="email"
/>

// Password输入框
<input
  value={password}
  onChange={handleChange}
  required
  className="shadow appearance-none border border-red rounded w-full py-2 px-3 text-grey-darker mb-3"
  id="password"
  name="password" // 新增name属性
  type="password"
  placeholder="Password"
/>

同时建议给useState初始化空字符串,避免初始值为undefined:

const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')

修改后,表单输入会正确更新state,提交时后端能接收到完整的字段值,Mongoose验证通过后即可正常存入数据。

内容的提问来源于stack exchange,提问作者kanwar 31k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:18:16