You need to enable JavaScript to run this app. React中useEffect钩子的异步函数内如何正确更新数组?
优惠活动
大模型
产品
解决方案
定价
更多

React中useEffect钩子的异步函数内如何正确更新数组?

问题根因

你当前代码的核心问题是:循环发起的单条item config请求都是异步操作,不会阻塞后续代码执行,你在发起所有请求后立刻执行了setItems,此时绝大多数config请求还未返回响应,空的或只有部分数据的数组被提前写入state,导致渲染不全。


解决方案

使用Promise.all批量等待所有异步config请求全部完成后,再统一更新state。推荐同时用async/await改写嵌套的.then回调,避免回调地狱,提升代码可读性。

修改后的组件代码如下:

const Dashboard = () => {
  const authUser = useContext(AuthUserContext);
  const firebase = useContext(FirebaseContext);

  const [error, setError] = useState<string|null>(null);
  const [firebaseToken, setFirebaseToken] = useState<string|null>(null);
  const [items, setItems] = useState<Array<ItemModel>>([]);

  useEffect(() => {
    if(!authUser || !firebase) return;
    
    const getItems = async () => {
      try {
        const userId = authUser.id;
        const token = await firebase.doGetIdToken();
        setFirebaseToken(token);

        // 拉取用户item列表
        const itemResults:Array<ItemModel> = await Client.getData(`items/${userId}`, token);

        // 把每个item转换成拉取config的promise
        const itemPromiseList = itemResults.map(async (item:ItemModel) => {
          const newConfig:ConfigModel = await Client.getData(`/items/config/${item.id}`, token);
          return {
            ...item,
            config: newConfig
          }
        });

        // 等待所有config请求完成,拿到完整的带config的item列表再更新state
        const itemResultsWithConfigs = await Promise.all(itemPromiseList);
        setItems(itemResultsWithConfigs);
      } catch (err) {
        setError("Unable to connect to database");
      }
    }

    getItems();
  }, [authUser, firebase])

  return (
    <>
      <ul>
        {
          items.map((item:ItemModel) => {
              return <li key={item.id}>{item.name}</li>
          })
        }
      </ul>
    </>
  );
}

export default Dashboard;

注意事项

  • 如果需要兼容单条config请求失败不影响整体列表渲染,可以给每个单条config请求添加catch逻辑,返回带默认config值的item对象即可,避免Promise.all整体抛出异常。
  • 原代码中setFirebaseToken是异步更新state,如果你需要在其他地方使用该token,不要依赖本次更新后立即读取state,直接使用当前拿到的token变量即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 03:27:04