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

React + Vite:工具文件如何向组件返回认证错误信息?

解决方案

这里提供几种实用的方式,把AuthContext中的认证错误传递到LoginPage处理并展示:

方法1:通过Promise的reject返回错误信息

在AuthContext的认证函数中,当请求失败或验证不通过时,用Promise.reject()抛出错误对象,LoginPage调用时通过.catch()捕获并处理。

AuthContext.jsx示例:

import { createContext, useContext } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const login = async (credentials) => {
    try {
      const response = await fetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(credentials)
      });

      if (!response.ok) {
        // 解析后端返回的错误信息
        const errorData = await response.json();
        // 通过reject传递错误
        return Promise.reject(new Error(errorData.message || '登录失败'));
      }

      const user = await response.json();
      // 处理登录成功逻辑,比如存储token
      return user;
    } catch (err) {
      // 捕获网络类异常,再向外抛出
      return Promise.reject(new Error(err.message || '网络异常,请稍后重试'));
    }
  };

  return (
    <AuthContext.Provider value={{ login }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

LoginPage.jsx示例:

import { useState } from 'react';
import { useAuth } from './AuthContext';

const LoginPage = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const { login } = useAuth();

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError(''); // 清空之前的错误提示

    try {
      await login({ username, password });
      // 登录成功后的跳转逻辑
      window.location.href = '/dashboard';
    } catch (err) {
      // 捕获错误并展示
      setError(err.message);
    }
  };

  return (
    <div className="login-container">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          placeholder="用户名"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button type="submit">登录</button>
        {/* 错误信息展示区 */}
        {error && <p className="error-message">{error}</p>}
      </form>
    </div>
  );
};

export default LoginPage;

方法2:在AuthContext中维护错误状态,组件直接读取

在AuthContext中添加error状态和clearError方法,认证失败时更新这个状态,LoginPage直接通过useAuth获取错误信息展示。这种方式适合多个组件需要共享认证错误的场景。

AuthContext.jsx示例:

import { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [error, setError] = useState('');

  const clearError = () => setError('');

  const login = async (credentials) => {
    clearError(); // 请求前清空旧错误
    try {
      const response = await fetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(credentials)
      });

      if (!response.ok) {
        const errorData = await response.json();
        setError(errorData.message || '登录失败');
        return; // 终止后续逻辑
      }

      const user = await response.json();
      // 处理登录成功逻辑
    } catch (err) {
      setError(err.message || '网络异常,请稍后重试');
    }
  };

  return (
    <AuthContext.Provider value={{ login, error, clearError }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

LoginPage.jsx示例:

import { useState } from 'react';
import { useAuth } from './AuthContext';

const LoginPage = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const { login, error, clearError } = useAuth();

  // 用户输入时清空错误提示
  const handleInputChange = (e, setter) => {
    setter(e.target.value);
    clearError();
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    await login({ username, password });
    // 登录成功后的跳转逻辑
  };

  return (
    <div className="login-container">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={username}
          onChange={(e) => handleInputChange(e, setUsername)}
          placeholder="用户名"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => handleInputChange(e, setPassword)}
          placeholder="密码"
        />
        <button type="submit">登录</button>
        {error && <p className="error-message">{error}</p>}
      </form>
    </div>
  );
};

export default LoginPage;

方法3:直接抛出错误,组件用try/catch捕获

和方法1逻辑类似,但在AuthContext的函数中直接抛出错误,组件调用时用try/catch捕获处理。

AuthContext.jsx示例:

import { createContext, useContext } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const login = async (credentials) => {
    const response = await fetch('/api/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(credentials)
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || '登录失败');
    }

    const user = await response.json();
    return user;
  };

  return (
    <AuthContext.Provider value={{ login }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

LoginPage.jsx示例:

import { useState } from 'react';
import { useAuth } from './AuthContext';

const LoginPage = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const { login } = useAuth();

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');

    try {
      await login({ username, password });
      window.location.href = '/dashboard';
    } catch (err) {
      setError(err.message);
    }
  };

  return (
    <div className="login-container">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          placeholder="用户名"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button type="submit">登录</button>
        {error && <p className="error-message">{error}</p>}
      </form>
    </div>
  );
};

export default LoginPage;

选择建议

  • 若仅LoginPage需要处理错误,方法1或3更灵活,错误处理逻辑集中在组件内部。
  • 若多个组件需要共享认证错误状态,方法2更合适,错误状态统一维护在Context中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:37:20