You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MERN Stack构建管理员登录页面时遭遇TypeError: Cannot read property 'username' of undefined错误求助

MERN Stack 管理员登录页面: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

火山引擎 最新活动