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

MERN基础应用前端无法向后端传递数据问题求助

MERN应用表单数据无法传递到后端,ValidationError问题解决

问题描述

开发基础MERN应用时,前端提交表单后,后端返回ValidationError,提示所有字段均为必填项,但前端已正常填写数据。

前端代码

import { useState } from 'react';

const SurveyForm = () => {
  const [name, setName] = useState('');
  const [gender, setGender] = useState('male');
  const [nationality, setNationality] = useState('');
  const [email, setEmail] = useState('');
  const [phoneNumber, setPhoneNumber] = useState('');
  const [address, setAddress] = useState('');
  const [message, setMessage] = useState('');
  const [hiddenText, setHiddenText] = useState('');

  const handleSubmit = async(e) => {
    e.preventDefault();
    if (hiddenText !== '') {
      alert('表单提交疑似垃圾信息。');
      return;
    }
    const newSurvey = {
      name,
      gender,
      nationality,
      email,
      phoneNumber,
      address,
      message
    };
    console.log(newSurvey)
    const response = await fetch(`http://localhost:5000/survey/add-survey`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name,
        gender,
        nationality,
        email,
        phoneNumber,
        address,
        message
      })
    });
    const jsona = await response.json();
    console.log(jsona);
    setName('');
    setGender('');
    setNationality('');
    setEmail('');
    setPhoneNumber('');
    setAddress('');
    setMessage('');
 
    alert('表单提交成功!');
   
  }
  return (
   <div className="min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12">
 <div className="relative py-3 ">
   <div className="relative  bg-white shadow-lg sm:rounded-3xl sm:p-20">
     <h1 className="text-2xl font-bold mb-8 text-center">Survey Form</h1>
     <form onSubmit={handleSubmit} className="space-y-6">
       <div>
         <label htmlFor="name" className="block text-sm font-medium text-gray-700">Name:</label>
         <input id="name" name="name" type="text" autoComplete="name" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={name} onChange={(e) => setName(e.target.value)} />
       </div>
       <div>
         <label htmlFor="gender" className="block text-sm font-medium text-gray-700">Gender:</label>
         <select id="gender" name="gender" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={gender} onChange={(e) => setGender(e.target.value)}>
           <option value="male">Male</option>
           <option value="female">Female</option>
           <option value="other">Other</option>
         </select>
       </div>
       <div>
         <label htmlFor="nationality" className="block text-sm font-medium text-gray-700">Nationality:</label>
         <input id="nationality" name="nationality" type="text" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={nationality} onChange={(e) => setNationality(e.target.value)} />
       </div>
       <div>
         <label htmlFor="email" className="block text-sm font-medium text-gray-700">Email:</label>
         <input id="email" name="email" type="email" autoComplete="email" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={email} onChange={(e) => setEmail(e.target.value)} />
       </div>
       <div>
         <label htmlFor="phoneNumber" className="block text-sm font-medium text-gray-700">Phone Number:</label>
         <input id="phoneNumber" name="phoneNumber" type="tel" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={phoneNumber} onChange={(e) => setPhoneNumber(e.target.value)} />
       </div>
       <div>
         <label htmlFor="address" className="block text-sm font-medium text-gray-700">Address:</label>
         <textarea id="address" name="address" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={address} onChange={(e) => setAddress(e.target.value)}></textarea>
       </div>
       <div>
         <label htmlFor="message" className="block text-sm font-medium text-gray-700">Message:</label>
         <textarea id="message" name="message" required className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={message} onChange={(e) => setMessage(e.target.value)}></textarea>
       </div>
       <input type="text" value={hiddenText} onChange={(e) => setHiddenText(e.target.value)} style={{display: 'none'}} />
       <button type="submit" className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Submit</button>
     </form>
   </div>
 </div>
</div>

  );
};
export default SurveyForm;

后端代码

const express = require('express');
const router = express.Router();
const Survey = require('../models/Survey');

router.get('/get-surveys', (req, res) => {
    Survey.find({}, (err, surveys) => {
      if (err) {
        res.status(500).send('获取调查数据出错');
      } else {
        res.status(200).json(surveys);
      }
    });
  });


router.post('/add-survey', async (req, res) => {
    const surveyData = req.body;
    console.log(surveyData)
    const newSurvey = await Survey.create(surveyData);
    newSurvey.save()
    .then(() => {
        res.status(200).json({ message: '调查保存成功' })
    })
    .catch((err) => {
      console.log(err)
        res.status(500).json({ message: '保存调查出错' });
        });
  });

module.exports = router;

报错信息

ValidationError: 调查验证失败:message: 路径message是必填项。, address: 路径address是必填项。, phoneNumber: 路径phoneNumber是必填项。, email: 路径email是必填项。, nationality: 路径nationality是必填项。, gender: 路径gender是必填项。, name: 路径name是必填项。

解决方案

1. 配置JSON解析中间件

后端未解析JSON请求体,导致req.body为空对象,Mongoose因此触发必填字段验证错误。在后端主文件(如app.js或server.js)中添加以下代码:

const express = require('express');
const app = express();

// 解析JSON格式的请求体
app.use(express.json());

// 挂载调查路由
const surveyRouter = require('./routes/survey');
app.use('/survey', surveyRouter);

2. 修复后端路由代码

避免async/await和.then()混用,且Survey.create()方法已自动保存文档,无需额外调用.save():

router.post('/add-survey', async (req, res) => {
  try {
    const newSurvey = await Survey.create(req.body);
    res.status(200).json({ message: '调查保存成功' });
  } catch (err) {
    console.log(err);
    res.status(500).json({ message: '保存调查出错' });
  }
});

3. 处理跨域问题(若存在)

如果前端和后端端口不同,需配置CORS:

  • 安装cors包:
npm install cors
  • 在后端主文件添加:
const cors = require('cors');
app.use(cors());

内容的提问来源于stack exchange,提问作者Ashgreninja55

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:44:55