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

为何useEffect不响应localStorage中accessToken的变化?

问题原因

你的第二个useEffect没触发,核心问题出在这行代码:

const token = localStorage.getItem("accessToken");

这行代码只在组件首次渲染或者重新渲染时执行一次,拿到当时localStorage里的token值。之后当service文件移除localStorage中的accessToken时,组件并不会自动重新渲染,这个token变量的值也就不会更新。

而第二个useEffect的依赖数组是这个固定的token值——只要它不变,useEffect就不会重新执行。所以哪怕localStorage里的token被删了,这个token还是初始渲染时的旧值,自然触发不了登出逻辑。

修复方案

这里给你两种可行的修复方式,按需选择:

方案一:监听storage事件+自定义事件

浏览器的storage事件能监听其他标签页/窗口对localStorage的修改,但当前页面内修改不会触发它。所以我们可以结合自定义事件,覆盖当前页面内修改的场景:

const [sessionState, setSessionState] = useState<SessionStateType>({
    status: "anon",
    accessToken: null,
});

// 页面加载时初始化登录状态
useEffect(() => {
    const token = localStorage.getItem("accessToken");
    if (token) {
        setSessionState({ status: "auth", accessToken: token });
    }
}, []);

useEffect(() => {
    // 监听其他页面修改localStorage的情况
    const handleStorageChange = (e: StorageEvent) => {
        if (e.key === "accessToken" && !e.newValue) {
            setSessionState({ status: "anon", accessToken: null });
        }
    };
    window.addEventListener("storage", handleStorageChange);

    // 监听当前页面内移除token的自定义事件
    const handleTokenRemoved = () => {
        setSessionState({ status: "anon", accessToken: null });
    };
    window.addEventListener('tokenRemoved', handleTokenRemoved);

    // 组件卸载时移除监听
    return () => {
        window.removeEventListener("storage", handleStorageChange);
        window.removeEventListener('tokenRemoved', handleTokenRemoved);
    };
}, []);

然后在你的service文件中,移除token时触发自定义事件:

// service文件中移除token的逻辑
localStorage.removeItem("accessToken");
window.dispatchEvent(new CustomEvent('tokenRemoved'));

方案二:把token纳入React状态管理,同步到localStorage

不要直接依赖localStorage作为状态来源,而是把accessToken存在React状态里,同时同步到localStorage。这样状态变化会自动触发组件重新渲染,逻辑更清晰:

// 初始化时从localStorage读取token
const [sessionState, setSessionState] = useState<SessionStateType>(() => {
    const savedToken = localStorage.getItem("accessToken");
    return savedToken ? { status: "auth", accessToken: savedToken } : { status: "anon", accessToken: null };
});

// 封装统一的token更新方法
const updateSession = (newToken: string | null) => {
    if (newToken) {
        localStorage.setItem("accessToken", newToken);
        setSessionState({ status: "auth", accessToken: newToken });
    } else {
        localStorage.removeItem("accessToken");
        setSessionState({ status: "anon", accessToken: null });
    }
};

之后在service文件里,不管是获取到新token还是需要移除token,都调用这个updateSession方法,而不是直接操作localStorage。这样组件状态和localStorage始终保持同步,不需要额外监听就能自动触发登出逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:55:10