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

React应用中Context.Provider的setToken状态更新失效问题

问题分析与解决方案

你的问题核心在于React useState的异步更新特性和闭包捕获旧状态,导致你误以为setToken没更新状态,实际上状态已经在更新,但你在错误的时机访问了旧值。

具体问题点

  1. setToken回调里的闭包问题
    你在changeToken里用了setToken的回调函数,但回调里打印的token还是旧值——因为这个回调是在当前渲染周期的闭包中,捕获的是更新前的token状态。React的状态更新后,需要等到下一次渲染才会拿到新值。

  2. fetchData递归调用时机错误
    在拿到新的accessToken后,你立刻调用await fetchData(),但此时token状态还没完成更新,第二次fetch请求依然会用旧的token,导致看起来状态没更新。

修复步骤

1. 修正changeToken的日志逻辑

去掉setToken的回调,直接打印传入的newToken(这就是即将更新的新值),如果需要监听token的变化,用useEffect:

const changeToken = (newToken) => {
  setToken(newToken);
  console.log("buraay geldii change : ", newToken);
};

// 新增useEffect监听token变化,打印最新值
useEffect(() => {
  console.log("yenilenen token ", token);
}, [token]);

2. 修改fetchData,支持传入临时token

让fetchData可以接受一个可选的token参数,优先使用传入的新token,避免等待状态更新的异步延迟:

const fetchData = async (overrideToken) => {
  // 优先用传入的新token,没有则用当前状态的token
  const currentToken = overrideToken || token;
  console.log(isVerifyLogin);
  console.log(currentToken); // 这里打印的是正确的token
  try {
    const response = await fetch("http://localhost:8080/api/get-db", {
      headers: {
        Authorization: `Bearer ${currentToken}`,
      },
    });
    if (!response.ok) {
      const response2 = await fetch(
        "http://localhost:8080/api/auth/refreshToken",
        {
          method: "POST",
          headers: {
            Accept: "application/json",
            "Content-type": "application/json",
          },
          body: JSON.stringify({
            refreshToken: refresh,
          }),
        }
      );
      if (response2.ok) {
        const data2 = await response2.json();
        // 先更新状态
        changeToken(data2.accessToken);
        // 用新token直接调用fetchData,不用等状态更新
        await fetchData(data2.accessToken);
      } else {
        setIsVerifyLogin(false);
      }
    } else {
      setIsVerifyLogin(true);
      const data = await response.json();
      setUsers(data);
    }
  } catch (error) {
    console.error("Error fetching data:", error);
    setIsVerifyLogin(false);
  }
};

3. 导入useEffect

在TokenProvider的开头补充导入:

import React, { createContext, useState, useEffect } from "react";

为什么这样修复?

  • 用overrideToken参数直接传递新token,绕开了useState异步更新的延迟,确保第二次fetch用的是最新的accessToken。
  • 用useEffect监听token变化,能准确获取到更新后的状态值,避免闭包导致的旧值问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:54:52