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

React调用API先返回空响应后返回数据问题求助

问题原因
  • 代码中请求成功后先执行setIsLoaded(true),再执行setItems(result)。在React 17及更早版本中,异步回调里的多次状态更新会依次触发重渲染:
    1. 第一次执行setIsLoaded(true)后,isLoaded变为true,触发重渲染,此时items还未更新,仍是初始的空数组,所以console.log打印空值
    2. 紧接着执行setItems(result),再次触发重渲染,此时items已更新为接口返回的数据,所以第二次打印正常
  • 若使用React 18+版本仍出现该问题,大概率是开启了严格模式,开发环境下严格模式会额外执行一次useEffect检测副作用,该问题仅在开发环境出现,不会影响生产环境。
  • 额外注意:你调用的接口返回的根数据是对象,实际业务常用的天气列表在result.dataseries字段中,直接存储整个result对象会和你初始化的数组类型不匹配,后续遍历操作可能报错。
解决方案
  1. 调整状态更新顺序,先更新items再更新isLoaded
(result) => {
  // 先更新数据,再更新加载状态
  setItems(result); 
  setIsLoaded(true);
}

改动后,第一次状态更新修改items时,isLoaded还是false,触发的重渲染仍走Loading分支,不会执行业务逻辑;第二次更新isLoaded为true时,items已经是最新值,业务逻辑拿到的就是正常数据。
2. 合并状态更新,把三个状态合并为一个状态对象,一次性更新

// 初始化合并状态
const [requestState, setRequestState] = useState({
  error: null,
  isLoaded: false,
  items: []
});

// 请求成功后一次性更新所有状态
(result) => {
  setRequestState({
    isLoaded: true,
    items: result,
    error: null
  })
}

// 后续判断逻辑从requestState中取对应字段即可
  1. React 18+版本可以用startTransition包裹状态更新,强制批量处理多次更新
import { startTransition } from 'react';

// 更新时用startTransition包裹
(result) => {
  startTransition(() => {
    setIsLoaded(true);
    setItems(result);
  })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 06:36:07