首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在反应中通过getBoundingClientRect接收元素尺寸

在反应中通过getBoundingClientRect接收元素尺寸
EN

Stack Overflow用户
提问于 2020-03-27 07:14:55
回答 2查看 6.5K关注 0票数 7

我想以可靠的方式找出DOM元素的维度。

我的考虑是为此使用getBoundingClientRect。

代码语言:javascript
运行
复制
  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作出反应,而不是对rect的更改作出反应。显然,浏览器中组件的绘制尚未完成,因为尺寸总是为0。

如果我在useEffect之外做了所有的事情,那么它就能工作。在控制台中,我看到2次0的值,然后是正确的维度。

使用useEffect:

在useEffect之外:

但是,我想保存状态中的维度,为此我需要useEffect。

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

溶液

这不是自我反应的问题。这是离子V5反应中的一个缺陷。

通常你可以这样做:

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

代码语言:javascript
运行
复制
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];
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-27 10:33:06

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

代码语言:javascript
运行
复制
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>
  );
}`
票数 5
EN

Stack Overflow用户

发布于 2020-11-15 14:03:00

如果性能是您关心的问题,那么在使用ResizeObserver的基础上,我将使用这个库来避免布局破坏:https://github.com/ZeeCoder/use-resize-observer

请注意,由于这个特殊原因,它没有使用getBoundingClientReact():https://gist.github.com/paulirish/5d52fb081b3570c81e3a

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60881446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档