reactjs - 在 React 中通过 getBoundingClientRect 接收元素的尺寸

标签 reactjs react-hooks dimensions getboundingclientrect ionic-react

我想以可靠的方式找出 DOM 元素的尺寸。

我的考虑是为此使用 getBoundingClientRect 。

  const elementRef = useRef<HTMLUListElement | null>(null);
  const [dimensions, setDimensions] = useState<DOMRect | undefined>();

  const element: HTMLUListElement | null = elementRef.current;

  /**
   * Update dimensions state.
   */
  const updateDimensions = useCallback(() => {
    if (!element) return;

    setDimensions(element.getBoundingClientRect());
  }, [element, setDimensions]);

  /**
   * Effect hook to receive dimensions changes.
   */
  useEffect(() => {
    if (element) {
      updateDimensions();
    }
  }, [element, updateDimensions]);

这种方法的问题是 useEffect 只对 elementRef.current 使用react,而不对 rect 的变化使用react。显然浏览器中组件的绘制还没有完成,因为尺寸总是0。

如果我在 useEffect 之外做整个事情,那么它就可以工作。在控制台中,我看到 0 的 2 倍值,然后是正确的尺寸。

使用效果:

Dimensions with useEffect

在 useEffect 之外:

Dimensions outside useEffect

但是,我想在状态中保存尺寸,为此我需要 useEffect。

我如何使用 getBoundingClientRect 来实现这一点,或者还有其他方法可以做到这一点?

解决方案

这不是自我 react 的问题。这是 ionic V5 react 中的一个错误。

通常你可以这样做:

https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node

但这里有一个问题:

https://github.com/ionic-team/ionic/issues/19770

我的解决方法是使用:https://github.com/que-etc/resize-observer-polyfill
import { RefCallback, useCallback, useState } from 'react';
import ResizeObserver from 'resize-observer-polyfill';


export function useDimensions(): [RefCallback<HTMLElement | null>, DOMRect | undefined] {
  const [dimensions, setDimensions] = useState<DOMRect | undefined>();

  const ref: RefCallback<HTMLElement | null> = useCallback((node: HTMLElement | null) => {
    if (node) {
      setDimensions(node.getBoundingClientRect().toJSON());

      const resizeObserver = new ResizeObserver((entries) => {
        if (entries.length) {
          setDimensions(entries[0].target.getBoundingClientRect().toJSON());
        }
      });

      resizeObserver.observe(node);

      return () => {
        resizeObserver.unobserve(node);
        resizeObserver.disconnect();
      };
    }
  }, []);

  return [ref, dimensions];
}

最佳答案

您可以使用 callBackRef 来实现所需的行为:

import React, { useCallback, useState } from "react";

export default function App() {
  const [dimensions, setDimensions] = useState(null);

  const callBackRef = useCallback(domNode => {
    if (domNode) {
      setDimensions(domNode.getBoundingClientRect());
    }
  }, []);

  return (
    <div>
      <h1 ref={callBackRef}>Measure me</h1>
    </div>
  );
}`

关于reactjs - 在 React 中通过 getBoundingClientRect 接收元素的尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60881446/

相关文章:

javascript - 在React/Redux中使用音频对象

javascript - Sendbird 消息服务在每个组 channel 中复制新消息

reactjs - 使用 `new` 关键字作为参数的 useState

如果表大小小于设定值,Java 将 JDialog 适配到 JTable

javascript - 类型错误 : Cannot set property 'src' of null

javascript - Redux-persist 不持久数量,但仍然持久购物车总数?

javascript - 跨多个组件重用 React.useCallback() 函数

javascript - 根据 API 响应递归呈现项目列表

android - 使用 "sp"单位而不是 "dp"单位来确定 View 的尺寸

c# - 获取远程图像尺寸