React项目中Zustand类方法调用后后续代码不执行问题
问题描述
在React项目中使用Zustand管理全局认证状态,同时编写了Auth API实现认证逻辑,但出现异常:当接口返回200状态码进入if (response.status === 200)分支后,this.setLogin语句之后的console.log("authenticated")和success=true代码完全不执行;但如果把这两行放在this.setLogin之前则能正常运行。
Zustand状态仓库代码:
import { create } from "zustand"; type AuthStore = { id: number | null; isLoggedIn: boolean; accessToken: string; setLogin: (token: string, id: number) => void; setLogout: () => void; test: () => void; }; export const useAuthStore = create<AuthStore>((set) => ({ id: null, isLoggedIn: false, accessToken: "", setLogin: (token, id) => set({ isLoggedIn: true, accessToken: token, id: id }), setLogout: () => set({ isLoggedIn: false, accessToken: "", id: null }), test: () => set((state) => { console.log(state.accessToken); return {}; }), }));
Auth API代码:
import { AxiosResponse, isAxiosError } from "axios"; import { UserAccountType } from "../types/userInfo.type"; import api from "./api"; import { useAuthStore } from "../store/authStore"; interface User { token: string; id: number; } export class AuthApi { private static setLogin(token: string, id: number): void { useAuthStore().setLogin(token, id); } static async login(userCred: Partial<UserAccountType>) { let success = false; let errorMessage = ""; try { const response = await api.post<User>("/auth/login", userCred, { withCredentials: true, }); if (response.status === 200) { const token = response.data.token; const id = response.data.id; this.setLogin(token, id); console.log("authenticated"); success = true; } } catch (err) { if (isAxiosError(err)) { const status = err.response?.status; console.log(err); switch (status) { case 401: errorMessage = "Invalid Email or Password. Try again or click Forgot password to reset it."; break; default: errorMessage = `${err.message}. Please try again.`; } } } return { success, errorMessage }; } }
问题原因与修复方案
核心问题
你在非React组件/自定义钩子的类方法中调用了Zustand的useAuthStore()钩子,违反了React钩子的使用规则——钩子只能在React组件顶层或自定义钩子内调用。此时React会抛出错误(可能被try/catch静默捕获),导致this.setLogin之后的代码无法执行。
修复步骤
修改AuthApi中的setLogin方法,改用Zustand提供的getState()方法获取store实例,而非调用钩子:
// 修改后的AuthApi代码 import { AxiosResponse, isAxiosError } from "axios"; import { UserAccountType } from "../types/userInfo.type"; import api from "./api"; import { useAuthStore } from "../store/authStore"; interface User { token: string; id: number; } export class AuthApi { private static setLogin(token: string, id: number): void { // 改用getState()获取store,避开React钩子调用限制 useAuthStore.getState().setLogin(token, id); } static async login(userCred: Partial<UserAccountType>) { let success = false; let errorMessage = ""; try { const response = await api.post<User>("/auth/login", userCred, { withCredentials: true, }); if (response.status === 200) { const token = response.data.token; const id = response.data.id; this.setLogin(token, id); console.log("authenticated"); success = true; } } catch (err) { if (isAxiosError(err)) { const status = err.response?.status; console.log(err); switch (status) { case 401: errorMessage = "Invalid Email or Password. Try again or click Forgot password to reset it."; break; default: errorMessage = `${err.message}. Please try again.`; } } else { // 新增:处理非Axios错误,避免遗漏报错信息 errorMessage = "An unexpected error occurred."; console.error(err); } } return { success, errorMessage }; } }
补充说明
useAuthStore.getState()是Zustand专为非React上下文(如工具类、API层)提供的状态访问方法,不会触发React重新渲染,仅用于读取或修改状态。- 建议完善catch块的错误处理逻辑,避免非Axios错误被静默忽略,方便后续排查问题。
内容的提问来源于stack exchange,提问作者Aslan
相关产品推荐
相关产品推荐

