brianmearns
brianmearns

Reputation: 9967

Callback when DOM is loaded in react.js

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

Upvotes: 115

Views: 386894

Answers (9)

naveen rai
naveen rai

Reputation: 1

Add the below code in app.js [initial js file] below and it will detect the window refresh:

    window.onload = () => {
      if (window.location.pathname != "/") {
        window.location = "/";
      }
    };

// const App = (props) => {

Upvotes: -1

Reza Babaei
Reza Babaei

Reputation: 1075

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

Upvotes: 2

Hitesh Ramola
Hitesh Ramola

Reputation: 340

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

Upvotes: 28

John
John

Reputation: 8946

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

Upvotes: 88

Bret
Bret

Reputation: 91

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.

Upvotes: 6

Christopher Adams
Christopher Adams

Reputation: 1300

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

Upvotes: 1

Shyam
Shyam

Reputation: 663

In modern browsers, it should be like

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

componentDidMount(){
     this.try();
}

Upvotes: 3

deepak prakash
deepak prakash

Reputation: 723

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

Upvotes: 6

brianmearns
brianmearns

Reputation: 9967

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.

Upvotes: 58

Related Questions