在React-App中使用React Portal(不在DOM之外)

时间:2019-07-04 22:17:32

标签: javascript reactjs

我想在我的React应用程序中实现模式。门户网站似乎对此非常好,但是我不想更改我的外部HTML结构。

HTML仍应为:

<div id="app"></div>

我不想在HTML结构中添加额外的div。

在App.js中,我尝试像这样添加root-modal-container:

class App extends Component {

  render() {
    return (
      <ResponsiveProvider>
        <div id="root-modal"></div>
        <Modal>
           <div>Modal :-)</div>
        </Modal>
      </ResponsiveProvider>
    );
  }
}

但是当尝试在Modal组件中 getElementById 时,我总是收到错误:null上的appendChild ...

问题在于,启动Modal-component时,root-modal-div不会渲染。

任何解决方案如何使我可以从应用程序中的任何位置直接在关卡中渲染Modals?

您可以看到未运行的代码here。取消注释HTML的第二行以使代码运行。

1 个答案:

答案 0 :(得分:0)

您可以使用React门户网站做到这一点,但是这有点尴尬,您必须充分参与DOM本身,才能跨这样的应用程序呈现(而不是完全外部的DOM节点)。

我刚刚发布了一个库来解决这个确切的问题,因为尽管门户网站可以实现,但这并不容易。

您可以在https://github.com/httptoolkit/react-reverse-portal上查看完整的详细信息。

在您的示例中,解决方案如下所示:

import React from "react";
import ReactDOM from "react-dom";
import * as portals from "react-reverse-portal";

class App extends React.Component {
  constructor(props) {
    super(props);
    // Create a portal node: the link between the two ends of the portal
    this.modalNode = portals.createPortalNode();
  }

  render() {
    // Place an OutPortal somewhere: this is where the content will appear.
    // Could be many levels deep in your app - you just need to get the modalNode
    // there. For complex cases you might want to put it in a context to distribute it.
    return <div>
      <Child modalNode={this.modalNode} />
      <portals.OutPortal node={this.modalNode} />
    </div>;
  }
}

const Child = props => {
  // Place an InPortal somewhere: this is where the content is defined
  return <portals.InPortal node={props.modalNode}>
    <Modal>
      <div>Modal :-)</div>
    </Modal>
  </portals.InPortal>
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

在上面的内容中:Child定义了它想要显示的某些模式内容,而App定义了应该显示模式内容的空间。您可以使用它链接应用程序的各个部分,并在它们之间发送渲染的内容。希望有帮助!