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

React向Express发POST请求时出现Cannot read property of 'undefined'错误排查

登录认证问题排查及修复方案

我帮你梳理下问题所在,你的代码里有几处关键错误,导致不管密码对错都返回401,同时前端还弹出Cannot read property 'data' of undefined的类型错误。

一、后端代码的核心问题

1. matchPasswords 方法的错误实现

这是导致401的根本原因:你在matchPasswords里用了bcrypt.compare的回调版本,但在async函数里这种写法完全行不通——当你给bcrypt.compare传回调时,它不会返回Promise,所以await bcrypt.compare(...)其实是在等待一个undefined,最终matchPasswords总是返回undefined。这就导致foundUser && (await foundUser.matchPasswords(password))这个条件永远为false,不管密码是否正确,后端都会走到else分支返回401。

修复后的matchPasswords:

userSchema.methods.matchPasswords = async function (enteredPassword) {
  // 直接返回bcrypt.compare的Promise,async函数会自动处理resolve的布尔值
  return bcrypt.compare(enteredPassword, this.password);
};

2. Mongoose findOne 混合使用async/await和回调

你在async函数里给findOne传了回调,这会让await完全失效——Mongoose的findOne如果传回调,就不会返回Promise,你的await等于白写,代码逻辑会变得混乱,错误处理也容易出问题。

修复后的authUser控制器(纯async/await写法):

const authUser = asyncHandler(async (req, res, next) => {
  console.log('Hit');
  const { email, password } = req.body;

  // 用await直接获取查询结果,抛弃回调写法
  const foundUser = await User.findOne({ email });

  if (!foundUser) {
    res.status(401);
    return next(new Error('Invalid credentials'));
  }

  // 调用修复后的matchPasswords,得到正确的布尔值
  const isPasswordMatch = await foundUser.matchPasswords(password);

  if (isPasswordMatch) {
    res.json({
      _id: foundUser._id,
      name: foundUser.name,
      email: foundUser.email,
      token: generateWebToken(foundUser._id),
    });
  } else {
    res.status(401);
    next(new Error('Invalid credentials'));
  }
});

二、前端Action Creator的笔误

你的loginUser错误处理部分有个明显的笔误:把error.response.data.message写成了error.response.message.data,这就导致当后端返回错误时,你试图读取error.response.message.data,但error.response.message根本不存在,所以会抛出Cannot read property 'data' of undefined的错误。

修复后的错误处理代码:

export const loginUser = ({ email, password }) => async (dispatch) => {
  try {
    dispatch({ type: USER_LOGIN_REQUEST });
    const config = {
      headers: {
        'Content-Type': 'application/json',
      },
    };
    const { data } = await axios.post(
      '/api/v1/users/login',
      { email, password },
      config
    );
    dispatch({ type: USER_LOGIN_SUCCESS, payload: data });
  } catch (error) {
    dispatch({
      type: USER_LOGIN_FAIL,
      payload: error.response && error.response.data.message
        ? error.response.data.message  // 修正了属性读取顺序
        : error.message,
    });
  }
};

最后验证

先修复后端的两个问题,再修正前端的笔误:

  • 用正确凭证登录时,后端会返回200和用户数据,前端触发USER_LOGIN_SUCCESS
  • 用错误凭证登录时,后端返回401,前端正确捕获错误信息触发USER_LOGIN_FAIL

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:18:13