MERN Stack构建管理员登录页面时遭遇TypeError: Cannot read property 'username' of undefined错误求助
我来帮你一步步拆解这个问题,先看错误核心:TypeError: Cannot read property 'username' of undefined——这说明你在尝试访问req.body.username时,req.body是undefined,结合你的代码,我找到了几个关键问题:
错误信息
(node:11648) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'username' of undefined at /home/dell/Desktop/Coding/photography/backend/index.js:24:24 at Layer.handle [as handle_request] (/home/dell/Desktop/Coding/photography/backend/node_modules/express/lib/router/layer.js:95:5) at invokeCallback (/home/dell/Desktop/Coding/photography/backend/node_modules/raw-body/index.js:224:16) (Use `node --trace-warnings ...` to show where the warning was created) (node:11648) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:11648) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
你的代码片段
React AdminLogin 组件
import React, { useState } from "react"; const AdminLogin = () => { const [username, setUserName] = useState(""); const [password, setPassword] = useState(""); const checkAdmin = async () => { const response = await fetch("http://localhost:1377/admin/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username, password, }), }); const data = await response.json(); console.log(data); }; return ( <> <div className="admin-form"> <div className="admin"> <div className="admin-username admin-input"> <label htmlFor="username" className="label"> Username: </label> <input type="text" placeholder="Enter admin username" className="input" id="username" value={username} onChange={(e) => setUserName(e.target.value)} /> </div> <div className="admin-password admin-input"> <label htmlFor="password" className="label"> Password: </label> <input type="password" placeholder="Enter your password" className="input" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button className="submit" onClick={checkAdmin}> Submit </button> </div> </div> </> ); }; export default AdminLogin;
后端 index.js
// Importing modules and packages const express = require("express"); const app = express(); const cors = require("cors"); const mongoose = require("mongoose"); const User = require("./models/user.model"); // Connecting to MongoDB // Ignore <username> and <password> in MongoDB URL mongoose.connect( "mongodb+srv://<username>:<password>@photography.4ssji.mongodb.net/<project>? retryWrites=true&w=majority" ); // Setting up middleware app.use(cors()); app.use(express.json()); // Creating express server app.post("/admin/login", async (res, req) => { const user = await User.findOne({ username: req.body.username, }); if (user) { return res.json({ status: "ok", admin: true }); } else { return res.json({ status: "error", admin: false }); } }); app.get((req, res, next) => { res.send("404 not found"); }); app.listen(1377, () => { console.log("Server started successfully on PORT: 1377"); });
User 模型
const mongoose = require("mongoose"); const User = new mongoose.Schema( { name: { type: String, required: true }, password: { type: String, required: true }, }, { collection: "user-data" } ); const model = mongoose.model("UserData", User); module.exports = model;
问题分析与解决方案
1. 路由回调参数顺序颠倒(最核心错误)
Express 的路由回调函数参数顺序是 (req, res)(请求在前,响应在后),你写反成了(res, req)。这导致你拿到的req实际上是响应对象,res是请求对象,自然req.body是undefined,也就无法读取username属性。
修复:
修改POST路由的回调参数顺序:
app.post("/admin/login", async (req, res) => { // ... 后续代码 });
2. 数据库字段名不匹配
你的前端传的是username,但User模型里定义的字段是name,这会导致数据库查询永远返回null,即使输入正确的用户名也会判定为不存在。
修复:
修改User模型,把name改成username(更符合登录场景的语义):
const User = new mongoose.Schema( { username: { type: String, required: true }, // 这里改成username password: { type: String, required: true }, }, { collection: "user-data" } );
注意:如果数据库里已经有旧数据,需要同步更新数据的字段名,或者前端改成传name(不推荐)。
3. 缺少Promise错误处理
你的异步路由里没有处理数据库查询可能抛出的错误,导致出现UnhandledPromiseRejectionWarning。
修复:
用try/catch包裹异步操作,捕获并处理错误,同时建议添加密码验证逻辑(生产环境不要明文存密码,要使用bcrypt等哈希加密):
app.post("/admin/login", async (req, res) => { try { const { username, password } = req.body; // 先检查请求参数是否存在 if (!username || !password) { return res.json({ status: "error", admin: false, message: "请输入用户名和密码" }); } const user = await User.findOne({ username }); if (user) { // 密码验证(生产环境用哈希对比) if (user.password === password) { return res.json({ status: "ok", admin: true, message: "登录成功" }); } else { return res.json({ status: "error", admin: false, message: "密码错误" }); } } else { return res.json({ status: "error", admin: false, message: "用户名不存在" }); } } catch (err) { console.error("登录验证出错:", err); return res.status(500).json({ status: "error", admin: false, message: "服务器内部错误" }); } });
4. 404路由配置错误
你当前的app.get((req, res, next) => {...})没有指定路径,不会生效。需要改成匹配所有未定义的路由:
修复:
app.get('*', (req, res) => { res.send("404 not found"); });
5. 额外建议:验证MongoDB连接状态
可以添加MongoDB连接的状态监听,确保连接成功,同时检查Atlas的IP白名单是否允许本地访问:
mongoose.connect( "mongodb+srv://<username>:<password>@photography.4ssji.mongodb.net/<project>?retryWrites=true&w=majority" ) .then(() => console.log("MongoDB连接成功")) .catch(err => console.error("MongoDB连接失败:", err));
修改后的完整后端index.js示例
// Importing modules and packages const express = require("express"); const app = express(); const cors = require("cors"); const mongoose = require("mongoose"); const User = require("./models/user.model"); // Connecting to MongoDB mongoose.connect( "mongodb+srv://<username>:<password>@photography.4ssji.mongodb.net/<project>?retryWrites=true&w=majority" ) .then(() => console.log("MongoDB连接成功")) .catch(err => console.error("MongoDB连接失败:", err)); // Setting up middleware app.use(cors()); app.use(express.json()); // Admin login route app.post("/admin/login", async (req, res) => { try { const { username, password } = req.body; if (!username || !password) { return res.json({ status: "error", admin: false, message: "请输入用户名和密码" }); } const user = await User.findOne({ username }); if (user) { if (user.password === password) { return res.json({ status: "ok", admin: true, message: "登录成功" }); } else { return res.json({ status: "error", admin: false, message: "密码错误" }); } } else { return res.json({ status: "error", admin: false, message: "用户名不存在" }); } } catch (err) { console.error("登录验证出错:", err); return res.status(500).json({ status: "error", admin: false, message: "服务器内部错误" }); } }); // 404 route app.get('*', (req, res) => { res.send("404 not found"); }); app.listen(1377, () => { console.log("Server started successfully on PORT: 1377"); });
内容的提问来源于stack exchange,提问作者Moksh Singh Dangi




