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

React中API处理类异步调用下表单数据无法显示的问题

异步操作未等待导致React组件无法渲染API数据的解决方案

问题核心

你遇到的问题是异步操作未正确等待,导致组件在数据还未处理完成时就调用了setStat,此时user_opening_percentages还是初始值;而当你修改代码触发热重载时,类实例已经完成了数据处理,所以能显示数据。另外,ChessGameFetcher内部属性的变化不会触发React组件重新渲染,必须确保在异步流程完成后,通过setState传递最新数据。

具体问题点

  1. fetchOpenings函数中创建ChessGameFetcher实例后,没有调用异步的init()方法,直接获取user_opening_percentages,此时数据还未加载和处理。
  2. 即使调用了init(),也没有等待它完成就执行setStat,导致拿到的是初始空数据。

修复方案

步骤1:修改ChessGameFetcher的init方法,返回处理后的数据

让init方法返回最终的user_opening_percentages,确保异步流程完成后能拿到最新数据:

async init(): Promise<PercentageInfo[]> {
  await this.fetchGameArchives();
  this.logOpenings();
  this.returnOpeningData();
  this.getPercentages();
  return this.user_opening_percentages; // 返回处理好的数据
}

步骤2:修改组件中的fetchOpenings函数,等待异步操作完成

在fetchOpenings中调用init()并等待其完成,再设置状态:

async function fetchOpenings() {
  setLoading(true); // 开启加载状态
  try {
    const gameFetcher = new ChessGameFetcher(username);
    // 等待init异步操作完成,拿到处理好的数据
    const openingStats = await gameFetcher.init();
    console.log(openingStats);
    setStat(openingStats); // 此时数据已准备好,设置状态触发渲染
  } catch (err) {
    console.error("获取数据失败:", err);
  } finally {
    setLoading(false); // 关闭加载状态
  }
}

步骤3:优化组件渲染逻辑

添加loading状态的显示,同时确保列表基于最新的stat状态渲染:

function OpeningForm() {
  const [stat, setStat] = useState<PercentageInfo[]>([]); // 初始化为空数组更合理
  const [username, setUsername] = useState("");
  const [loading, setLoading] = useState(false);
  const [submitted, setSubmitted] = useState(false);

  async function fetchOpenings() {
    setLoading(true);
    try {
      const gameFetcher = new ChessGameFetcher(username);
      const openingStats = await gameFetcher.init();
      setStat(openingStats);
    } catch (err) {
      console.error("获取数据失败:", err);
    } finally {
      setLoading(false);
    }
  }

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    setSubmitted(true);
    fetchOpenings();
  };

  return (
    <>
      <form onSubmit={handleSubmit}>
        <label>
          输入用户名:
          <input
            type="text"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
          />
        </label>
        <button type="submit" disabled={loading}>
          {loading ? "加载中..." : "提交"}
        </button>
      </form>

      {loading ? (
        <p>加载数据中...</p>
      ) : submitted ? (
        stat.length > 0 ? (
          <ul>
            {stat.map((st, index) => (
              <li key={index}>{st.toString()}</li>
            ))}
          </ul>
        ) : (
          <p>暂无数据</p>
        )
      ) : null}
    </>
  );
}

额外优化建议

  • 避免在组件中直接依赖类实例的内部状态,尽量通过异步方法返回数据,确保数据流清晰。
  • 给stat的初始值设置为空数组,比默认的PercentageInfo实例更符合实际场景,避免渲染无意义的初始数据。
  • 添加错误处理,防止API请求失败导致组件异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:07:24