Using ResizeObserver in React class component

12,781

Solution 1

EDIT: Davidicus's answer below is more complete, look there first

ResizeObserver can't go in the constructor because the div doesn't exist at that point in the component lifecycle.

I don't think you can get around the extra div because react components reduce to html elements anyway.

Put this in componentDidMount and it should work:

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

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

Solution 2

ComponentDidMount would be the best place to set up your observer but you also want to disconnect on 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>
    );
  }
}

Solution 3

I was fighting a the similar problem recently with the difference that my app is predominantly using hooks and functional components.

Here is an example how to use the ResizeObserver within a React functional component (in typescript):

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>;
Share:
12,781
noblerare
Author by

noblerare

Updated on June 16, 2022

Comments

  • noblerare
    noblerare almost 2 years

    I am using React 15 on Chrome and want to hook up an event listener to detect changes to a parent container. After looking around for options, I came across ResizeObserver and am not sure how to get it to work in my project.

    Currently, I am putting it in my constructor but it does not seem to print any text and I am not sure what to put in the observe call.

    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>
            );
        }
    }
    

    Ideally, I also don't want to wrap RealComponent in a div and give that div an id. Is there a way to the RealComponent directly?

    My goal is to observe any resize changes to the RealComponent but MyComponent is fine too. What should I put in the somethingGoesHere slot?

    EDIT:

    For the sake of getting something to work, I bit the bullet and wrapped a div tag around RealComponent. I then gave it an id <div id="myDivTag"> and changed the observe call:

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

    However, when running this, I get:

    Uncaught TypeError: resizeObserver.observe is not a function

    Any help would be greatly appreciated.

  • Johns3n
    Johns3n over 4 years
    Is it good react practice to create instances inside a component like that?
  • Christophe
    Christophe about 2 years
    What TS target are you using? I am getting an error with target:es6.
  • Vočko
    Vočko about 2 years
    @Christophe I think 2015. ResizeObserver is not supported in any version of IE, you might need to use some polyfill like github.com/que-etc/resize-observer-polyfill. I luckily don't have to worry about ie. support anymore.