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

React自定义useAuth Hook错误值不更新,登录失败仍跳转

问题原因分析

你遇到的问题核心有两点:

  1. 错误无法触发组件的异常捕获逻辑:你的useAuth里的login函数在捕获错误后,只更新了error状态但没有把错误重新抛出。这就导致Login组件里的await login(user)不会进入catch块,不管登录成功失败,都会直接执行navigate("/dashboard")。
  2. 组件未利用error状态做跳转拦截:就算组件能拿到更新后的error,当前代码也没在提交后检查这个状态来阻止错误情况下的跳转。
修复方案

第一步:修改useAuth.js,让错误可以被调用方捕获

在每个异步函数的catch块里,设置完error状态后把错误重新抛出,这样调用组件就能通过try/catch感知到错误:

import { useState } from "react";
import { account } from "../appwrite/config";
import { ID } from "appwrite";

const useAuth = () => {
  const [error, setError] = useState(null);

  const signup = async (user) => {
    setError(null); // 每次调用先清空旧错误
    try {
      await account.create(
        ID.unique(),
        user.email,
        user.password,
        user.username
      );
    } catch (error) {
      console.log(error);
      setError(error.message);
      throw error; // 重新抛出错误,让调用方捕获
    }
  };

  const login = async (user) => {
    setError(null);
    try {
      await account.createEmailSession(user.email, user.password);
    } catch (error) {
      console.log(error);
      setError(error.message);
      throw error; // 新增该行,抛出错误
    }
  };

  const logout = async () => {
    setError(null);
    try {
      await account.deleteSession("current");
    } catch (error) {
      console.log(error);
      setError(error.message);
      throw error; // 保持逻辑一致性
    }
  };
  return { signup, login, logout, error };
};

export default useAuth;

第二步:修改Login.js,仅在登录成功时跳转,并显示错误信息

现在login函数会抛出错误,catch块会触发,同时我们可以把error状态显示在页面上提示用户:

import { useState } from "react";
import useAuth from "../hooks/useAuth";
import { useNavigate } from "react-router-dom";

const Login = () => {
  const [user, setUser] = useState({});
  const { login, error } = useAuth();
  const navigate = useNavigate();

  const handleChange = (e) => {
    setUser({ ...user, [e.target.name]: e.target.value });
  };
  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await login(user);
      // 只有登录成功才执行跳转
      navigate("/dashboard");
    } catch (error) {
      console.log("登录失败:", error);
    }
  };

  return (
    <div>
      <h1>Log In</h1>
      {/* 新增错误提示区域 */}
      {error && <p style={{ color: "red", margin: "1rem 0" }}>{error}</p>}
      <form onSubmit={handleSubmit}>
        <div>
          <label htmlFor="email">Email</label>
          <input onChange={handleChange} type="email" name="email" id="email" />
        </div>
        <div>
          <label htmlFor="password">Password</label>
          <input
            onChange={handleChange}
            type="password"
            name="password"
            id="password"
          />
        </div>
        <button>Log In</button>
      </form>
    </div>
  );
};

export default Login;

额外说明

  • 每次调用login/signup前先调用setError(null),是为了清空上一次的错误状态,避免旧错误干扰新的操作。
  • 如果你不想用try/catch,也可以在Login组件里用useEffect监听error的变化来做提示,但用try/catch控制跳转逻辑会更直接可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:35:25