如何解决React Hooks和Material-UI:在使用中的首次加载时无法获取对话框引用
第一次尝试加载我的组件时,我试图获取对材质用户界面对话框的DOM节点的引用,但是引用始终为undefined
。
这是我的方法:
import React,{ useEffect,useRef } from "react";
import {
Dialog,DialogTitle,DialogContent,DialogContentText
} from "@material-ui/core";
export default function App() {
const dialogRef = useRef();
useEffect(() => {
console.log("Dialog Ref");
console.log(dialogRef.current);
},[]);
return (
<Dialog open ref={dialogRef}>
<DialogTitle>Ref Test Dialog</DialogTitle>
<DialogContent>
<DialogContentText>
Please check the console to see if a ref to this Dialog was logged.
</DialogContentText>
</DialogContent>
</Dialog>
);
}
Material UI Dialog API docs指出“ ref被转发到根元素”,而我的方法基于React useRef docs,所以看来这应该可行。
实际上,当我对<div>
元素使用相同的方法时,它确实起作用。我是否缺少某些东西,或者这是Material UI中的错误?
这是该问题的“有效”示例:
https://codesandbox.io/s/hopeful-agnesi-3i0p3?file=/src/App.js
解决方法
对话框leverages Modal,而对话框依次leverages Portal。 Material-UI的Portal组件使用React的createPortal API来将Dialog呈现在父组件的DOM层次之外。
createPortal
的参数之一是要在其中渲染的DOM节点。 Dialog支持通过container prop控制此DOM节点(默认为document.body)。 Material-UI gets the DOM node of the container in an effect,之后是renders the Dialog。
因此,在组件的初始呈现中,Material-UI的Portal组件将识别容器并触发Portal组件的后续呈现,而后者实际上将呈现Dialog。
您可以使用disablePortal prop禁用此功能,在这种情况下,对话框将为rendered immediately,并且引用将按预期工作。
如果要保留默认的门户网站行为,则可以将回调函数作为ref传递,以便在ref首次可用时执行代码。这样做时,对收到的论点采取防御措施很重要。每当ref发生变化时,都会调用回调函数,其中包括在卸载期间将其变回null的情况。
还有一个onRendered prop,您可以在其中放置此功能;但是docs表示将在v5中弃用并删除它,而改用ref。
这是您的沙盒的修改版本,演示了使用ref的回调函数:
import React,{ useEffect,useRef } from "react";
import {
Dialog,DialogTitle,DialogContent,DialogContentText
} from "@material-ui/core";
export default function App() {
const dialogRef = useRef();
useEffect(() => {
console.log("Dialog Ref",dialogRef.current);
},[]);
return (
<Dialog
open
ref={(node) => {
dialogRef.current = node;
// Do your work requiring the node here,but make sure node isn't null.
console.log("ref function",node);
}}
onRendered={() => console.log("onRendered",dialogRef.current)}
onEntering={() => console.log("onEntering",dialogRef.current)}
onEntered={() => console.log("onEntered",dialogRef.current)}
>
<DialogTitle>Ref Test Dialog</DialogTitle>
<DialogContent>
<DialogContentText>
Please check the console to see if a ref to this Dialog was logged.
</DialogContentText>
</DialogContent>
</Dialog>
);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。