React createPortal 调用失败,因为 document.body 不存在?
React createPortal call fails because document.body doesn't exist?
我有一个模态对话框的 React 组件。当我不对它做任何特别的事情时它工作得很好:
return (
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
);
但是,显示对话框的规定方法是将其显示在 DOM 文档的底部,而不是嵌入恰好调用它的任何组件中,包括组件的外部 DOM 元素甚至可能不允许。 (事实上 ,在一种情况下,我从呈现 table 行的组件内部调用模态对话框,在 TR 处。它 "works" 但它会触发 Chrome 的错误消息控制台,因为在 TR 中只允许 TH 和 TD)。这样做的方法是 ReactDOM.createPortal
:
import ReactDOM from 'react-dom';
...
return (ReactDOM.createPortal(
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
), document.body);
调用 ReactDOM.createPortal
,将 document.body
作为其第二个参数,应该在主体的末尾呈现组件。但它给了我一个错误:"Target container is not a DOM element".
在我显示对话框时,页面和其中的所有其他内容都已经存在,因此正文存在。
我已经尝试了另一种我已经解释过的方法,即在文档的外部 HTML 结构的末尾创建一个显式的 div 作为模态的容器:
<div id="root"></div>
<div id="modalRoot"></div>
然后用 document.getElementById('modalRoot')
代替 document.body
。但这给了我同样的错误。
我为此找到的唯一答案涉及在第一次呈现时通过文档的 HEAD 部分中的脚本调用模态的情况,因此主体尚不存在。在这些情况下,建议将脚本移至文档末尾。在我的例子中,显示对话框是为了响应我在已经呈现的文档中的某些操作。
有什么想法吗?
import ReactDOM from 'react-dom';
...
return ReactDOM.createPortal(
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
), document.body);
您的函数应该 return 对象 return 由 ReactDOM.createPortal
函数编辑。您在 return 函数的开头添加了额外的 (
。参考:https://reactjs.org/docs/portals.html#usage
我有一个模态对话框的 React 组件。当我不对它做任何特别的事情时它工作得很好:
return (
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
);
但是,显示对话框的规定方法是将其显示在 DOM 文档的底部,而不是嵌入恰好调用它的任何组件中,包括组件的外部 DOM 元素甚至可能不允许。 (事实上 ,在一种情况下,我从呈现 table 行的组件内部调用模态对话框,在 TR 处。它 "works" 但它会触发 Chrome 的错误消息控制台,因为在 TR 中只允许 TH 和 TD)。这样做的方法是 ReactDOM.createPortal
:
import ReactDOM from 'react-dom';
...
return (ReactDOM.createPortal(
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
), document.body);
调用 ReactDOM.createPortal
,将 document.body
作为其第二个参数,应该在主体的末尾呈现组件。但它给了我一个错误:"Target container is not a DOM element".
在我显示对话框时,页面和其中的所有其他内容都已经存在,因此正文存在。
我已经尝试了另一种我已经解释过的方法,即在文档的外部 HTML 结构的末尾创建一个显式的 div 作为模态的容器:
<div id="root"></div>
<div id="modalRoot"></div>
然后用 document.getElementById('modalRoot')
代替 document.body
。但这给了我同样的错误。
我为此找到的唯一答案涉及在第一次呈现时通过文档的 HEAD 部分中的脚本调用模态的情况,因此主体尚不存在。在这些情况下,建议将脚本移至文档末尾。在我的例子中,显示对话框是为了响应我在已经呈现的文档中的某些操作。
有什么想法吗?
import ReactDOM from 'react-dom';
...
return ReactDOM.createPortal(
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
), document.body);
您的函数应该 return 对象 return 由 ReactDOM.createPortal
函数编辑。您在 return 函数的开头添加了额外的 (
。参考:https://reactjs.org/docs/portals.html#usage