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

如何让React Toastify展示后端自定义登录错误?

解决React Toastify无法显示后端自定义错误的问题

问题说明

使用MongoDB开发登录功能,已集成react-toastify组件展示后端错误信息,但目前仅能显示普通提示,无法正确渲染后端自定义错误,前端控制台打印err.response.data.error显示undefined。

前端调用Toast的代码

const handleSubmit = async (e) => {
  e.preventDefault();
  try {
    const { data } = await axios.post(process.env.REACT_APP_LOGIN, {
      username, password
    });

    if (data.success === true) {
      setValues({ username: '', password: '' });
      toast.success("Sign in successfully");
      // 保存用户到本地存储
      if (typeof window !== "undefined") {
        localStorage.setItem("token", JSON.stringify(data));
      }
      navigate("/map");
    }
  } catch (err) {
    // 日志输出undefined
    console.log(`This is the error: ${err.response.data.error}`);
    toast.error(`There is an error: ${err.response.data.error}`);
  }
}

return (
  <div className='loginContainer'>
    <div className='logo'></div>
    <AddLocationAltIcon/>
    Pin
    <form className='loginForm'>
      <input type='text' className='usernameE' placeholder='username' onChange={handleChange('username')}/>
      <input type='password' className='passwordE' placeholder='password' onChange={handleChange('password')} />
      <button className='loginBtn' onClick={handleSubmit} type="submit">Login</button>
      <button onClick={() => navigate('/register')} className="loginRegister">
        Sign Up
      </button>
    </form>
  </div>
)

后端登录接口代码

exports.signin = async (req, res, next)=> {
  try {
    const { username, password } = req.body;
    // 检查用户名和密码是否存在
    if (!username || !password) {
      return next(new ErrorResponse(`Username and password are required`, 404))
    }
    // 检查用户名是否存在
    const user = await User.findOne({ username });
    if (!user) {
      return next(new ErrorResponse(`Invalid credentials`, 404))
    }

    // 验证密码是否匹配
    const isMatched = await user.comparePassword(password);
    if (!isMatched) {
      return next(new ErrorResponse(`Cannot log in, check your credentials`, 404))
    }

    generateToken(user, 200, res);
    
  } catch (error) {
    console.log(error);
    return next(new ErrorResponse(`Cannot log in, check your credentials`, 404))
  }
}

ErrorResponse自定义错误类

class ErrorResponse extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
  }
}

module.exports = ErrorResponse;

解决方案

1. 补充后端错误处理中间件

后端需要添加全局错误处理中间件,将ErrorResponse的消息和状态码格式化后返回给前端,确保响应包含error字段:

// 全局错误处理中间件
app.use((err, req, res, next) => {
  // 默认状态码500,默认错误消息
  const statusCode = err.statusCode || 500;
  const errorMessage = err.message || 'Server Error';

  // 返回符合前端预期的JSON结构
  res.status(statusCode).json({
    success: false,
    error: errorMessage
  });
});

注:如果已有错误中间件,需确保返回的JSON结构包含error字段,对应前端读取的err.response.data.error。

2. 优化前端错误处理逻辑

在catch块中增加容错处理,避免因err.response不存在(如网络错误)导致的报错,同时确保正确读取错误消息:

catch (err) {
  // 使用可选链操作符安全访问嵌套属性
  const errorMsg = err.response?.data?.error || '登录失败,请稍后重试';
  console.log(`错误信息: ${errorMsg}`);
  toast.error(`登录错误: ${errorMsg}`);
}

3. 验证后端响应格式

打开浏览器开发者工具的Network标签,触发登录错误请求,查看响应的JSON内容,确认是否包含error字段且值为自定义错误消息。若格式不符,调整后端错误中间件的返回结构。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:15:44