Callback when DOM is loaded in react.js

Reactjs

Reactjs Problem Overview


I want to have a callback invoked on my react.js component when its 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>.

Reactjs Solutions


Solution 1 - Reactjs

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

Solution 2 - Reactjs

Looks like a combination of componentDidMount and componentDidUpdate will get the job done. The first is called after the initial rendering, when the DOM is available, the second is called after any subsequent renderings, once the updated DOM is available. In my case, I both have them delegate to a common function to do the same thing.

Solution 3 - Reactjs

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

Solution 4 - Reactjs

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

Solution 5 - Reactjs

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.

Solution 6 - Reactjs

In modern browsers, it should be like

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

componentDidMount(){
     this.try();
}

Solution 7 - Reactjs

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

Solution 8 - Reactjs

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

Solution 9 - Reactjs

seems it's working to me

const [isLoaded, setIsLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false); //this helps

useEffect(() => {
    setIsLoaded(true);
}, []);

useEffect(() => {
    if (isLoaded) {
        setIsPageLoaded(true);
    }
}, [isLoaded]);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbrianmearnsView Question on Stackoverflow
Solution 1 - ReactjsJohnView Answer on Stackoverflow
Solution 2 - ReactjsbrianmearnsView Answer on Stackoverflow
Solution 3 - ReactjsHitesh RamolaView Answer on Stackoverflow
Solution 4 - Reactjsdeepak prakashView Answer on Stackoverflow
Solution 5 - ReactjsBretView Answer on Stackoverflow
Solution 6 - ReactjsShyamView Answer on Stackoverflow
Solution 7 - ReactjsrealraifView Answer on Stackoverflow
Solution 8 - ReactjsChristopher AdamsView Answer on Stackoverflow
Solution 9 - ReactjsReza BabaeiView Answer on Stackoverflow