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

React中useRef偶发不更新仅打印object,无法获取元素宽高如何解决?

问题根因
  • 封装的useRefCallback本身逻辑无问题,偶发无法获取DOM节点的核心原因是 useRef对象的更新不会触发组件重渲染:
    • 组件首次渲染时ref.current初始值为null,此时将mapWidgetRef传入useResizeObserver,如果useResizeObserver内部仅在初始化阶段读取一次ref.current,且此时React尚未执行ref回调完成ref.current的赋值,就会读取到null值。后续ref.current完成赋值后,没有更新机制触发useResizeObserver重新执行、绑定新的DOM节点,最终导致宽高返回undefined
    • 问题偶发是受React渲染执行时序影响,不同运行环境、不同渲染负载下,ref回调的执行时机与自定义hook内部逻辑的执行先后顺序存在波动,因此会出现时好时坏的表现
修复方案

方案1:调整useRefCallback实现,返回状态化的DOM节点(优先选择)

将DOM节点存储在state中,ref更新时同步触发state更新,即可带动依赖该节点的hook自动重新执行:

import { useState, useCallback } from 'react';

function useRefCallback() {
  const [node, setNode] = useState(null);
  const setRef = useCallback((node) => {
    setNode(node);
  }, []);
  return [node, setRef];
}

调用侧直接将状态化节点传入useResizeObserver即可:

function MapWidget({ options }) {
  const [mapWidgetNode, setMapWidgetRef] = useRefCallback();
  const [mapWidgetWidth, mapWidgetHeight] = useResizeObserver(mapWidgetNode); 

  return (
    <div ref={setMapWidgetRef}>
    ...
    </div>
  );
}

该方案无需修改useResizeObserver的内部逻辑,只要useResizeObserver将传入的节点作为依赖项,即可自动在节点更新后重新绑定监听。

方案2:调整useResizeObserver内部逻辑,主动监听ref.current变化

如果不希望修改useRefCallback的实现,可以调整useResizeObserver的依赖项,确保ref.current更新时重新执行绑定逻辑:

import { useState, useEffect } from 'react';

function useResizeObserver(ref) {
  const [width, setWidth] = useState(undefined);
  const [height, setHeight] = useState(undefined);
  
  useEffect(() => {
    // 节点为空时跳过执行
    if (!ref.current) return;
    const observer = new ResizeObserver((entries) => {
      const { width: contentWidth, height: contentHeight } = entries[0].contentRect;
      setWidth(contentWidth);
      setHeight(contentHeight);
    });
    observer.observe(ref.current);
    return () => observer.disconnect();
  // 必须将ref.current加入依赖,触发节点更新时重新执行绑定
  }, [ref.current]);

  return [width, height];
}

注意不要仅将ref对象本身加入依赖数组,ref对象是稳定不变的,仅添加ref对象不会触发useEffect重新执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:24:03