在 react.js 中加载 DOM 时进行回调

我希望在页面上实际加载 DOM 元素(包括所有子节点)并准备就绪时,在 react.js 组件上调用回调。具体来说,我有两个组件,我想呈现相同的大小,选择最大的组件有更大的自然大小。

看起来 componentDidMount并不是我真正想要的,因为每个组件只调用一次,但是我希望在组件完成呈现时再次调用我的回调。我认为我可以在顶级 DOM 元素中添加一个 onLoad事件,但是我想这只适用于某些元素,比如 <body><img>

307565 次浏览

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.

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

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

In modern browsers, it should be like

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


componentDidMount(){
this.try();
}

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.

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

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

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