gpt4 book ai didi

javascript - React - componentDidUpdate() 无法找到由 render() 方法呈现的 DOM 对象

转载 作者:行者123 更新时间:2023-11-30 06:12:01 31 4
gpt4 key购买 nike

编辑:我编辑了代码以添加和使用 refs 而不是 document.getElementById .它没有解决问题。

编辑 2: 所以我用 mutationObserver 做了一些测试,结果是 componentDidUpdate()在实际插入节点之前 开始执行大约 100 毫秒!这绝对是问题所在。

但是,React 文档说 componentDidUpdate()仅在 render() 之后触发是否完全执行完毕?我在这里错过了什么吗?如果是这样,什么?我想要的只是让我的代码在来自 render() 的所有节点之后 执行已插入。

编辑 3:该问题已找到并修复。请引用我在下面发布的答案。感谢所有提供帮助的人。


所以我正在尝试为我的网站创建一个登录对话框。我正在使用 React 构建对话框并使用 FirebaseUI 来显示内容。我的问题是,在 React 通过 render() 呈现 DOM 节点之后状态变化的方法(从 open: falseopen: true ),componentDidUpdate()函数无法立即找到这些 DOM 节点。

class SignInModal extends React.Component {

constructor(props) {
super(props);
this.dialogTitle = React.createRef();
this.firebaseContainer = React.createRef();
}
state = {
open: false,
redirect: null,
preRedirectFunction: null,
};

handleClickOpen = (redirect, preRedirectFunction) => {

this.setState({
open: true,
redirect: redirect,
preRedirectFunction: preRedirectFunction,
});

}

componentDidUpdate() {
console.log("componentDidUpdate at time: ");
console.log(Date.now());
console.log("Sign in modal state: ")
console.log(this.state);

console.log("Dialog title: ")
console.log(this.dialogTitle.current);
console.log("Firebase container: ")
console.log(this.firebaseContainer.current);

/* setTimeout(function () {
var authUI = firebaseui.auth.AuthUI.getInstance();
if(authUI){
console.log("AuthUI found");
authUI.reset();
authUI.start('#firebaseui-auth-container', getUIConfig(authUI, SignInModalRendered.state.redirect,SignInModalRendered.state.preRedirectFunction));
}
else{
console.log("No AuthUI found");
startFirebaseUI("", SignInModalRendered.state.preRedirectFunction);
}
}, 200); */


}

handleClose = () => {
this.setState({
open: false,
redirect: null,
preRedirectFunction: null,
});
};

render() {
console.log("Rendering sign-in modal");
console.log("Sign in modal state: ")
console.log(this.state);

console.log("Dialog title: ")
console.log(this.dialogTitle.current);
console.log("Firebase container: ")
console.log(this.firebaseContainer.current);
return (
<div>
<Dialog
onClose={this.handleClose}
aria-labelledby="customized-dialog-title"
open={this.state.open}
>
<DialogTitle id="customized-dialog-title" ref={this.dialogTitle} onClose={this.handleClose} style={{textAlign: "center"}}>
{Date.now()}
</DialogTitle>
<DialogContent id="SignInDialogContainer">
<div id="firebaseui-auth-container" ref={this.firebaseContainer}></div>
<div id="loader">{Date.now()}</div>
</DialogContent>
</Dialog>
</div>
);
}
}

执行此代码时,代码在 authUI.start('#firebaseui-auth-container'.... 行失败因为它无法找到 DOM 节点。

使用编辑后的代码,我纯粹是想在 componentDidUpdate() 中获取控制台日志能够找到 Dialog Title 和 Firebase Container DOM 节点。他们仍然返回 null .

Date.now() within the DOM

Console log showing the Date.now()

但是, Date.now() 的输出DOM 和 componentDidUpdate() 中的函数函数(如上图所示)显示 componentDidUpdate() 中的代码在渲染 DOM 后 2 毫秒执行。那么为什么这行代码在 componentDidUpdate()内呢?无法找到它?

我发现 componentDidUpdate()在节点完成渲染 之前执行大约 100 毫秒。为什么会这样?以及如何让我的代码在 节点完成渲染后执行?

附加信息:我尝试将有问题的代码块放在 setTimeout 中具有 200ms 延迟的功能,并且运行完美。但我不想使用此解决方法,我想了解发生了什么。

最佳答案

因此,在 marzelin 的帮助下,谁指出了我正确的方向,我设法弄清楚了为什么 componentDidUpdate() 无法找到 DOM 元素。

事实上,简短的回答是 DOM 元素在代码执行时根本不存在。

我很困惑为什么 componentDidUpdate()render() 完成渲染其中的所有 DOM 元素之前触发。然后,阅读an answer to another similar question ,我意识到 componentDidUpdate() render() 函数中的最外层元素被呈现时,而不等待内部元素完成渲染。

然后我用一个新的 React 类替换了我需要操作的 DOM 元素,该类由仅该元素组成,并将我的代码放入 componentDidMount() 新类的方法。

这解决了我的问题。

我的新代码和更新后的代码:

class FirebaseContainer extends React.Component {

constructor(props){
super(props);
console.log("Passed props: ");
console.log(props);
this.firebaseContainer = React.createRef();
}

state = this.props.parentState;

componentDidMount() {
console.log("componentDidMount at time: ");
console.log(Date.now());
/* console.log("Sign in modal state: ")
console.log(this.state); */

console.log("Firebase container: ")
console.log(this.firebaseContainer.current);

var authUI = firebaseui.auth.AuthUI.getInstance();
if(authUI){
console.log("AuthUI found");
authUI.reset();
authUI.start('#firebaseui-auth-container', getUIConfig(authUI, this.state.redirect,this.state.preRedirectFunction));
}
else{
console.log("No AuthUI found");
startFirebaseUI("", this.state.preRedirectFunction);
}
}

render(){
console.log("Rendering Firebase container");
console.log("Firebase container state: ")
console.log(this.state);

console.log("Dialog title: ")
console.log(document.getElementById('customized-dialog-title'));
console.log("Firebase container: ")
console.log(document.getElementById('firebaseui-auth-container'));
return(
<div id="firebaseui-auth-container" ref={this.firebaseContainer}></div>
);
}
}

class SignInModal extends React.Component {

constructor(props) {
super(props);
this.dialogTitle = React.createRef();
}
state = {
open: false,
redirect: null,
preRedirectFunction: null,
};

handleClickOpen = (redirect, preRedirectFunction) => {

this.setState({
open: true,
redirect: redirect,
preRedirectFunction: preRedirectFunction,
});

}

handleClose = () => {
this.setState({
open: false,
redirect: null,
preRedirectFunction: null,
});
};

render() {
console.log("Rendering sign-in modal");
console.log("Sign in modal state: ")
console.log(this.state);
return (
<Dialog ref={this.dialogTitle}
onClose={this.handleClose}
aria-labelledby="customized-dialog-title"
open={this.state.open}
>
<DialogTitle id="customized-dialog-title" onClose={this.handleClose} style={{textAlign: "center"}}>
Please sign in
</DialogTitle>
<DialogContent id="SignInDialogContainer">
<FirebaseContainer parentState={this.state}/>
<div id="loader">{Date.now()}</div>
</DialogContent>
</Dialog>
);
}
}

关于javascript - React - componentDidUpdate() 无法找到由 render() 方法呈现的 DOM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58339793/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com