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

React Hooks组件在Accordion展开后重渲染获取正确offsetWidth方案求助

可行解决方案

方案1:使用双层requestAnimationFrame

利用requestAnimationFrame的执行时序特性,两层嵌套可以保证回调在浏览器完成当前帧的布局、绘制之后执行,此时就能读取到正确的offsetWidth值:

import { useEffect, useRef, useState } from 'react';

const InnerComponent = ({ isAccordionOpen }) => {
  const targetElRef = useRef(null);
  const [contentWidth, setContentWidth] = useState(0);

  useEffect(() => {
    // 手风琴关闭时跳过逻辑
    if (!isAccordionOpen) return;

    // 第一层raf等待DOM更新,第二层等待浏览器绘制完成
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        if (targetElRef.current) {
          setContentWidth(targetElRef.current.offsetWidth);
        }
      });
    });
  }, [isAccordionOpen]);

  return <div ref={targetElRef}>你的组件内容</div>;
};

方案2:使用ResizeObserver(推荐)

ResizeObserver是浏览器原生提供的元素尺寸监听API,会在目标元素尺寸发生变化时触发回调,不受组件渲染时机、元素显隐状态影响,不需要依赖外部传入的手风琴开闭状态,是稳定性最高的方案:

import { useEffect, useRef, useState } from 'react';

const InnerComponent = () => {
  const targetElRef = useRef(null);
  const [contentWidth, setContentWidth] = useState(0);

  useEffect(() => {
    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const currentWidth = entry.contentRect.width;
        // 过滤掉元素不可见时的0值无效更新
        if (currentWidth > 0) {
          setContentWidth(currentWidth);
        }
      }
    });

    if (targetElRef.current) {
      resizeObserver.observe(targetElRef.current);
    }

    // 组件卸载时销毁监听器避免内存泄漏
    return () => resizeObserver.disconnect();
  }, []);

  return <div ref={targetElRef}>你的组件内容</div>;
};

方案3:使用setTimeout 0延时兜底

把读取尺寸的逻辑放到宏任务队列执行,会等待当前的DOM更新、浏览器绘制完成后再执行,写法最简单,适合轻量场景:

useEffect(() => {
  if (!isAccordionOpen) return;
  setTimeout(() => {
    if (targetElRef.current) {
      setContentWidth(targetElRef.current.offsetWidth);
    }
  }, 0);
}, [isAccordionOpen]);

方案对比

  • 双层requestAnimationFrame:轻量无额外依赖,时序可控,适合手风琴无展开动画的场景
  • ResizeObserver:兼容性覆盖所有现代浏览器,自动监听所有尺寸变化场景,不需要绑定手风琴状态,为最优方案
  • setTimeout:写法最简单,但是时序优先级最低,极端场景下可能出现延迟,适合临时测试、简单场景使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:18:02