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

引入Apollo Client useQuery后tabs.current为null的问题求助

问题根源

你遇到的核心问题是useQuery的loading状态导致组件提前返回,跳过了tabs相关DOM的渲染:
当homepageLoading为true时,组件直接返回"Loading header",此时你的tabs容器(也就是tabs.current对应的DOM元素)根本没有被渲染到页面上,自然tabs.current会是null。即使后续数据加载完成组件重新渲染,之前依赖tab的useEffect执行时,也可能因为DOM还未完成挂载导致null问题。

解决方案

1. 保留tabs容器的渲染(即使在loading状态)

不要在loading时直接返回纯文本,而是渲染包含tabs结构的占位内容,保证tabs对应的DOM始终存在,这样useRef能稳定获取到引用:

// 替换原来的loading/error返回逻辑
if (homepageLoading) {
  // 渲染带tabs容器的骨架屏,或者空的结构
  return (
    <div className="your-tabs-container-class" ref={tabs}>
      {/* 骨架屏内容,比如空的tab面板 */}
      <div className="tab-panel-skeleton"></div>
    </div>
  );
}
if (homepageError) {
  return (
    <div className="error-container">
      Oops there has been an error: {homepageError.message}
    </div>
  );
}

2. 给heightFix函数加容错处理

避免因为tabs.current为null或者子元素不存在导致报错,在操作DOM前增加判断:

const heightFix = () => {
  // 先判断tabs.current是否存在
  if (!tabs.current) return;
  const targetPanel = tabs.current.children[tab - 1];
  if (targetPanel) {
    tabs.current.style.height = `${targetPanel.offsetHeight}px`;
  }
};

3. 修正useEffect的依赖项(移除eslint禁用)

原来的useEffect禁用了依赖检查,可能导致闭包问题(比如拿不到最新的tab或者tabs.current)。把heightFix加入依赖,同时可以用useCallback包裹确保回调更新:

// 用useCallback包裹heightFix,确保依赖变化时更新
const heightFix = useCallback(() => {
  if (!tabs.current) return;
  const targetPanel = tabs.current.children[tab - 1];
  if (targetPanel) {
    tabs.current.style.height = `${targetPanel.offsetHeight}px`;
  }
}, [tab]); // 依赖tab,因为tab变化时需要重新计算高度

useEffect(() => {
  heightFix();
}, [heightFix]); // 依赖heightFix,确保回调更新时执行
修改后的完整示例片段
function HomeHowItWorks() {
  const [tab, setTab] = useState(1);
  const [blockName, setBlockName] = useState("home");
  const tabs = useRef(null);

  useEffect(() => {
    console.log(tabs.current);
  }, [tabs]);

  const heightFix = useCallback(() => {
    if (!tabs.current) return;
    const targetPanel = tabs.current.children[tab - 1];
    if (targetPanel) {
      tabs.current.style.height = `${targetPanel.offsetHeight}px`;
    }
  }, [tab]);

  useEffect(() => {
    heightFix();
  }, [heightFix]);
 
  const {
    data: homepageData,
    error: homepageError,
    loading: homepageLoading,
  } = useQuery(getPageHomepage, {
    variables: { blockname: blockName },
  });

  console.log(homepageData);

  if (homepageLoading) {
    return (
      <div ref={tabs} className="your-tabs-container">
        <div className="tab-panel-skeleton"></div>
      </div>
    );
  }
  if (homepageError) {
    return <div>Oops there has been an error: {homepageError.message}</div>;
  }

  return (
    {/* 你的完整tabs渲染逻辑,确保tabs ref绑定到正确的容器上 */}
    <div ref={tabs} className="your-tabs-container">
      {/* 切换tab的按钮 */}
      <button onClick={() => setTab(1)}>Tab 1</button>
      <button onClick={() => setTab(2)}>Tab 2</button>
      {/* 面板内容,用homepageData填充 */}
      <div className="tab-panel">
        {homepageData?.pageContent}
      </div>
      {/* 其他面板... */}
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:40:34