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

React登录后Cookie未定义,需刷新页面才正常的问题求助

React登录后自定义Hook获取Token为undefined,刷新后恢复的解决方案

问题诊断

核心问题是自定义Hook未感知到登录时Cookie的更新:当前登录逻辑仅设置了Cookie和用户状态,但自定义Hook要么只在组件初始化时读取一次Cookie,要么依赖的Context未同步更新Token,导致导航到首页后Hook仍返回旧值(undefined),只有刷新页面时组件重新初始化,才会读取到最新的Cookie值。

解决方案

1. 同步Token到Context(推荐)

如果自定义Hook从Context获取Token,需在登录时将Token同步到Context,确保全局状态与Cookie一致:

修改登录逻辑,新增Token的Context更新:

const navigate = useNavigate();
const { setData, setToken } = useUserData(); // 确保Context暴露setToken方法

const handleLogin = async (data: FormValues) => {
    try {
        const res = await normalFetch.post("/auth/login", data);
        const { token, user } = res.data;
        
        cookies.set("sg-auth-token", token);
        setData(user);
        setToken(token); // 将Token同步到Context
        toast.success("Successfully logged in.");
        navigate("/");
    } catch (error: any) {
        isAxiosError(error) && toast.error(error.response?.data?.message);
        console.log(error);
    }
};

对应的Context定义需包含Token状态:

// UserDataContext.tsx
import { createContext, useContext, useState, ReactNode } from "react";

interface User {
  // 你的用户数据结构
}

interface UserData {
  user: User | null;
  token: string | null;
}

interface UserDataContextType {
  data: UserData;
  setData: (user: User) => void;
  setToken: (token: string) => void;
}

const UserDataContext = createContext<UserDataContextType | undefined>(undefined);

export const UserDataProvider = ({ children }: { children: ReactNode }) => {
  const [data, setDataState] = useState<UserData>({
    user: null,
    token: cookies.get("sg-auth-token") || null // 初始化从Cookie读取
  });

  const setData = (user: User) => {
    setDataState(prev => ({ ...prev, user }));
  };

  const setToken = (token: string) => {
    setDataState(prev => ({ ...prev, token }));
  };

  return (
    <UserDataContext.Provider value={{ data, setData, setToken }}>
      {children}
    </UserDataContext.Provider>
  );
};

export const useUserData = () => {
  const context = useContext(UserDataContext);
  if (!context) throw new Error("useUserData must be used within a UserDataProvider");
  return context;
};

此时自定义Hook直接从Context取Token:

const useAuthToken = () => {
  const { data } = useUserData();
  return data.token;
};

2. 让自定义Hook响应Cookie变化

如果Hook直接读取Cookie,可使用react-cookie库的useCookie Hook自动监听Cookie变化:

// 安装依赖:npm install react-cookie
import { useCookie } from "react-cookie";

const useAuthToken = () => {
  const [token] = useCookie("sg-auth-token");
  return token;
};

3. 手动实现Cookie监听(无第三方库)

通过自定义事件实现Cookie变化监听:

登录时触发事件

const handleLogin = async (data: FormValues) => {
    try {
        const res = await normalFetch.post("/auth/login", data);
        const token = res.data.token;
        
        cookies.set("sg-auth-token", token);
        // 触发自定义事件通知Token更新
        window.dispatchEvent(new Event("auth-token-updated"));
        
        setData(res.data.user);
        toast.success("Successfully logged in.");
        navigate("/");
    } catch (error: any) {
        isAxiosError(error) && toast.error(error.response?.data?.message);
        console.log(error);
    }
};

自定义Hook中监听事件

import { useState, useEffect } from "react";
import cookies from "你的Cookie库";

const useAuthToken = () => {
  const [token, setToken] = useState(cookies.get("sg-auth-token"));

  useEffect(() => {
    const handleTokenUpdate = () => {
      setToken(cookies.get("sg-auth-token"));
    };

    window.addEventListener("auth-token-updated", handleTokenUpdate);
    return () => window.removeEventListener("auth-token-updated", handleTokenUpdate);
  }, []);

  return token;
};

总结

优先选择同步Token到Context的方案,保证全局状态一致性;若需直接操作Cookie,使用react-cookie或自定义事件监听确保Hook实时获取最新Token值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:41:35