[reactjs] Callback when DOM is loaded in react.js

I want to have a callback invoked on my react.js component when it's DOM element (including all child nodes) is actually loaded on the page and ready. Specifically, I have two components that I want to render the same size, choosing the maximum of whichever component has the larger natural size.

It looks like componentDidMount is not really what I want because it is only called once per component, but I want my callback to be called again anytime the component is finished rendering. I thought I could add an onLoad event to the top level DOM element, but I guess that only applies for certain elements, like <body> and <img>.

This question is related to reactjs

The answer is


You can watch your container element using the useRef hook. Note that you need to watch the ref's current value specifically, otherwise it won't work.

Example:

  const containerRef = useRef();
  const { current } = containerRef;

  useEffect(setLinksData, [current]);

return (
    <div ref={containerRef}>
      // your child elements...
    </div>
)

In modern browsers, it should be like

try() {
     if (!$("#element").size()) {
       window.requestAnimationFrame(try);
     } else {
       // do your stuff
     }
};

componentDidMount(){
     this.try();
}

I applied componentDidUpdate to table to have all columns same height. it works same as on $(window).load() in jquery.

eg:

componentDidUpdate: function() {
        $(".tbl-tr").height($(".tbl-tr ").height());
    }

A combination of componentDidMount and componentDidUpdate will get the job done in a code with class components. But if you're writing code in total functional components the Effect Hook would do a great job it's the same as componentDidMount and componentDidUpdate.

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

https://reactjs.org/docs/hooks-effect.html


What I have found is that simply wrapping code in the componentDidMount or componentDidUpdate with a setTimeout with a time of 0 milliseconds ensures that the browser DOM has been updated with the React changes before executing the setTimeout function.

Like this:

componentDidMount() {
    setTimeout(() => {
        $("myclass") //  $ is available here
    }, 0)
}

This puts the anonymous function on the JS Event Queue to run immediately after the currently running React stack frame has completed.


Add onload listener in componentDidMount

class Comp1 extends React.Component {
 constructor(props) {
    super(props);
    this.handleLoad = this.handleLoad.bind(this);
 }

 componentDidMount() {
    window.addEventListener('load', this.handleLoad);
 }

 componentWillUnmount() { 
   window.removeEventListener('load', this.handleLoad)  
 }

 handleLoad() {
  $("myclass") //  $ is available here
 }
}

The below is what I came up with to wait for when the DOM is ready before trying to get a class using document.getElementsByClassName. I called this function from the componentDidMount() lifecycle method.

     changeIcon() {
            if (
                document.getElementsByClassName('YOURCLASSNAME')
                    .length > 0 &&
                document.getElementsByClassName('YOURCLASSNAME').length > 0
            ) {
                document.getElementsByClassName(
                    'YOURCLASSNAME'
                )[0].className = 'YOUR-NEW-CLASSNAME';
                document.getElementsByClassName(
                    'YOUR-OTHER-EXISTING-CLASSNAME'
                )[0].style.display = 'block';
            } else {
                setTimeout(this.changeIcon, 500);
            }
     }