在 React 类组件中使用 ResizeObserver

12

我正在使用Chrome浏览器上的React 15,并想连接一个事件监听器以检测父容器的变化。在寻找选项后,我发现了ResizeObserver,但不确定如何在我的项目中让它工作。

目前,我将其放在构造函数中,但似乎没有打印任何文本,而且我不知道在observe调用中放什么。

class MyComponent extends React.Component {
    constructor(props) {
        super(props);

        const resizeObserver = new ResizeObserver((entries) => {
            console.log("Hello World");
        });

        resizeObserver.observe(somethingGoesHere);
    }

    render() {
        return (
            <AnotherComponent>
                <YetAnotherComponent>
                </YetAnotherComponent>

                <CanYouBelieveIt>
                </CanYouBelieveIt>

                <RealComponent />
            </AnotherComponent>
        );
    }
}
理想情况下,我也不想用 div 包装 RealComponent 并给该 div 设置 id。有没有直接针对 RealComponent 的方法?
我的目标是观察 RealComponent 的任何调整大小变化,但 MyComponent 也可以。在 somethingGoesHere 插槽中应该放什么?
编辑:
为了让某些东西起作用,我咬紧牙关并在 RealComponent 周围包装了一个 div 标签。然后我给它一个 id <div id="myDivTag"> 并更改了 observe 调用:
resizeObserver.observe(document.getElementById("myDivTag"));

然而,运行此代码时,我遇到了以下问题:

Uncaught TypeError: resizeObserver.observe不是一个函数

任何帮助将不胜感激。

3个回答

19

ComponentDidMount 是设置观察者的最佳位置,但你也希望在 ComponentWillUnmount 上断开连接。

class MyComponent extends React.Component {
  resizeObserver = null;
  resizeElement = createRef();

  componentDidMount() {
    this.resizeObserver = new ResizeObserver((entries) => {
      // do things
    });

    this.resizeObserver.observe(this.resizeElement.current);
  }

  componentWillUnmount() {
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
  }

  render() {
    return (
      <div ref={this.resizeElement}>
        ...
      </div>
    );
  }
}

15

编辑:Davidicus在下面的回答更完整,请先查看那里。

由于组件生命周期的原因,ResizeObserver不能放在构造函数中,因为div在此时不存在。

我认为你无法绕过额外的div,因为React组件最终会减少到HTML元素。

将这个代码放在componentDidMount中应该就可以工作:

componentDidMount() {
   const resizeObserver = new ResizeObserver((entries) => {
        console.log("Hello World");
   });

   resizeObserver.observe(document.getElementById("myDivTag"));
}

在 React 中,像这样在组件内部创建实例是一个好的实践吗? - Johns3n

6

我最近遇到了一个类似的问题,不同的是我的应用程序主要使用钩子和函数组件。

以下是在React函数组件中(使用typescript)如何使用ResizeObserver的示例:

const resizeObserver = React.useRef<ResizeObserver>(new ResizeObserver((entries:ResizeObserverEntry[]) => {
    // your code to handle the size change
}));

const resizedContainerRef = React.useCallback((container: HTMLDivElement) => {
    if (container !== null) {
        resizeObserver.current.observe(container);
    }
    // When element is unmounted, ref callback is called with a null argument
    // => best time to cleanup the observer
    else {
        if (resizeObserver.current)
            resizeObserver.current.disconnect();
    }
}, [resizeObserver.current]);

return <div ref={resizedContainerRef}>
    // Your component content here
</div>;

你使用的 TS 目标是什么?我在目标为:es6 时遇到了一个错误。 - Christophe
@Christophe,我认为2015年的ResizeObserver在任何版本的IE中都不受支持,你可能需要使用一些polyfill,比如https://github.com/que-etc/resize-observer-polyfill。我很幸运不再需要担心IE的支持问题了。 - Vočko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接