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

MERN栈前端提交MongoDB文档时genre字段缺失问题排查

问题:React表单提交POST请求时genre字段缺失,后端直接插入正常
  • Express后端连接MongoDB正常,GET/POST路由工作正常,数据托管在Heroku
  • React前端表单提交POST请求时,文档能成功创建,但genre字段缺失
  • 前端控制台打印的newBook对象包含genre字段,但数据库、Heroku后端数据、书籍详情页均无该字段
  • 后端直接用脚本插入含genre的文档正常,且schema中genre设为必填(未传会报错)
  • genre是初始连接后新增到schema的,MongoDB App Services已包含该字段

前端相关代码

表单提交方法

const createBook = async (book) => {
    await fetch(url, {
      method: "post",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(book),
    });
    getBooks();
  };

React表单组件

const Create = ({ createBook }) => {

  const navigate = useNavigate();

  const [newBook, setNewBook] = useState({
    title: "",
    author: "",
    cover: "",
    year: "",
    overview: "",
    genre: "",
    price: "",
  });

  const handleChange = (event) => {
    setNewBook({
      ...newBook,
      [event.target.name]: event.target.value,
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    createBook(newBook);
    console.log(newBook)
    setNewBook({
      title: "",
      author: "",
      cover: "",
      year: "",
      overview: "",
      genre: "",
      price: "",
    });
    navigate("/")
  };

  return (
    <div className="create-form">
      <section>
        <form onSubmit={handleSubmit}>
          <input type="text" value={newBook.title} name="title" placeholder="title" onChange={handleChange}></input>
          <input type="text" value={newBook.author} name="author" placeholder="author" onChange={handleChange}></input>
          <input type="text" value={newBook.cover} name="cover" placeholder="cover (URL)" onChange={handleChange}></input>
          <input type="number" value={newBook.year} name="year" placeholder="year" onChange={handleChange}></input>
          <input type="text" value={newBook.overview} name="overview" placeholder="overview" onChange={handleChange}></input>
          <input type="text" value={newBook.genre} name="genre" placeholder="genre" onChange={handleChange}></input>
          <input type="number" value={newBook.price} name="price" placeholder="price" onChange={handleChange}></input>
          <input type="submit" value="Add Book"/>
        </form>
      </section>
    </div>
  );
};

后端相关代码

Mongoose Schema

const mongoose = require("mongoose");

const bookSchema = new mongoose.Schema(
  {
    title: {
      type: String,
      required: [true, "title cannot be empty"],
    },
    author: {
      type: String,
      required: [true, "author cannot be empty"],
    },
    cover: {
      type: String,
      required: [true, "cover cannot be empty"],
    },
    year: {
      type: Number,
      required: [true, "year cannot be empty"],
    },
    overview: {
      type: String,
      required: [true, "overview cannot be empty"],
    },
    genre: {
      type: String,
      required: [true, "genre cannot be empty"],
    },
    price: {
      type: Number,
      min: [0, "price cannot be negative"],
      required: [true, "price cannot be empty"],
    },
  },
  {
    timestamps: true,
  },
);

const Book = mongoose.model("Book", bookSchema);
module.exports = Book;

后端插入脚本(可正常工作)

const books = [
  {
    title: "Shutter Island",
    author: "Dennis Lehane",
    cover:
      "http://prodimage.images-bn.com/pimages/9780061898815_p0_v3_s1200x630.jpg",
    year: 2003,
    overview:
      "In 1954, widower U.S. Marshal Edward 'Teddy' Daniels and his new partner, Chuck Aule, go on a ferry boat to Shutter Island, the home of Ashecliffe Hospital for the criminally insane, to investigate the disappearance of a patient, Rachel Solando (who was incarcerated for drowning her three children).",
    genre: "Mystery",
    price: 7.99,
  },
  {
    title: "Hamlet",
    author: "William Shakespeare",
    cover:
      "https://www.memoriapress.com/wp-content/uploads/2018/07/Hamlet-Student-Cover-Saddle.jpg",
    year: 1603,
    overview:
      "The ghost of the King of Denmark tells his son Hamlet to avenge his murder by killing the new king, Hamlet's uncle. Hamlet feigns madness, contemplates life and death, and seeks revenge. His uncle, fearing for his life, also devises plots to kill Hamlet.",
    genre: "Tragedy",
    price: 4.99,
  },
];

db.Book.insertMany(books, {
  ordered: false,
})
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("books inserted into mongo");
  });

排查与解决方向

  1. 确认Heroku后端已部署最新schema代码
    genre是新增字段,大概率本地更新了schema,但Heroku上的后端代码仍是旧版本(未包含genre字段)。重新部署后端到Heroku,确保schema已同步更新。

  2. 验证POST请求的实际发送数据
    用浏览器开发者工具的Network面板查看POST请求的Payload,确认genre字段是否真的被发送到后端。有时候控制台打印的newBook正确,但序列化或发送环节出现异常。

  3. 检查后端POST路由的处理逻辑
    确认后端接收请求时,是否正确解析JSON,且没有在保存前意外过滤genre字段。比如解构req.body时是否漏掉了genre:

    // 错误示例:解构时遗漏genre
    const { title, author, cover, year, overview, price } = req.body;
    const book = new Book({ title, author, cover, year, overview, price });
    

    若为此情况,修改解构代码加入genre即可。

  4. 检查Mongoose的strict模式
    Mongoose默认开启strict: true,会过滤schema中未定义的字段。如果后端schema未更新,genre会被当成未知字段过滤,这也回到第一点:确保后端部署了最新schema。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:35:27