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

如何等待useEffect执行完成后再获取自定义Hook返回的有效值

问题根因

React 组件的渲染逻辑是同步执行的,useEffect 会在组件首次渲染完成后才触发执行。因此你封装的自定义 Hook 首次调用时,异步请求还未发起,就会先返回 useState 初始化的空对象;等 useEffect 内的请求完成触发 setData 后,才会触发二次渲染返回真实的数组数据,所以会出现两次打印结果。

修复方案

最通用的实现方式是在自定义 Hook 中新增加载状态标识,调用侧判断加载完成后再使用数据,修改后的代码如下:

  • second.js 代码修改
import { useState, useMemo, useEffect } from 'react';
import _ from 'lodash';

// 修正原函数名笔误,和调用侧的 useGetDataArray 对齐
export const useGetDataArray = ({ name, id } = {}) => {
  // 初始值和返回类型对齐,改为空数组
  const [data, setData] = useState([]);
  // 新增加载状态标记
  const [isLoading, setIsLoading] = useState(true);

  const index = useMemo(() => {
    console.log("in useMemo");
    const client = thirdPartyProvider;
    return client;
  }, []);

  useEffect(() => {
    console.log("in useEffect");
    index
      .search(name, {
        numberOfResults: 12,
      })
      .then(res => {
        setData(_.get(res, "result", []));
      })
      .finally(() => {
        // 请求结束后标记加载完成
        setIsLoading(false);
      })
  // 补充请求参数name到依赖数组,避免参数变更时不重新请求
  }, [index, name]);

  return { data, isLoading };
};
  • first.js 代码修改
const { data: dataArray, isLoading } = useGetDataArray({ name, id });
// 仅在加载完成后使用/打印数据
if (!isLoading) {
  console.log("Data Array: ", dataArray);
}
注意事项
  • 不要试图阻塞 React 同步渲染流程等待异步请求返回,这不符合 React 的渲染规则
  • 原代码的 useEffect 依赖数组漏了请求参数 name,会导致 name 变更时不会重新拉取数据,需要补充到依赖中
  • 原自定义 Hook 的函数名存在笔误,少了字母 a,导致调用侧和导出的函数名不匹配,需要修正

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:06:03