将 ReactDOM.createPortal() 与 document.body 一起使用是否安全?

IT技术 javascript html reactjs
2021-05-14 17:48:03

据我所知,它可能是一个坏主意ReactDOM.render()document.body但是使用ReactDOM.createPortal()with有什么问题document.body吗?

试图寻找当你渲染到身体时 React 变得疯狂的例子,所以我可以用 createPortal 测试它,但我找不到任何。

为了将事情放在上下文中,这是我正在谈论的示例用法:

import React from 'react';
import ReactDOM from 'react-dom';

export default class Modal extends React.Component {
    render() {
        return ReactDOM.createPortal(
            <div className='modalContainer'>
                <div className='modalBox'>
                    {this.props.children}
                </div>
            </div>,
            document.body
        );
    }
}

这种模式没有遇到任何问题,但我想知道在我开始添加更多库时是否会产生后果。

2个回答

我很确定相同的规则适用于门户网站ReactDOM.render. 根据您提供门户文档,从 React 的角度来看,门户确实是 React 应用程序的子级(考虑例如合成 DOM 事件传播的方向),但实际上门户位于单独的上下文中,其中React 仍然需要跟踪状态变化并与 DOM 保持同步。

如果这种上下文的父body元素元素,那么通过 3rd 方工具插入元素一样,同样数量的不想要的惊喜也会受到威胁,如Dan Abramov 的文章中所述简单地说:由于来自第 3 方的那些 DOM 更改发生在 React 控制之外,但是修改了在 React 控制下的 DOM 部分,这可能导致冲突和不一致。

@RIYAJ KHAN 在他的评论中提出的另一点是,如果门户突然成为应用程序的父级,尤其是当 React 以相反的方式看待它们时会发生什么?我至少能想到的是原生DOM 事件传播合成DOM 事件传播之间的不一致,这两者会在应用程序和门户容器之间以相反的方向传播事件,如果您经常使用这两种类型的事件处理(例如,合成在React 组件的事件处理程序和RxJS 运算符中本机事件处理程序)。

最后但并非最不重要的一点是,如果您有更多这样的门户,应该在顶级 DOM 级别,您是否要body为所有这些门户重用再加上上面的2点会造成混乱。

最安全的方法是divbodyjust for the portal创建专用的s ,这样它们就保持干净并且没有不需要的魔法。

到目前为止,我们在 Material-UI 上的经验是它是安全的:https : //github.com/mui-org/material-ui/issues/21626我们还没有看到使用该库的 100 多位开发人员之一报告的任何限制。