是否可以将反应上下文注入到反应根之外的div(在主体下)

Posted

技术标签:

【中文标题】是否可以将反应上下文注入到反应根之外的div(在主体下)【英文标题】:Is it possible to inject react context to div outside the root in react (under the body) 【发布时间】:2019-12-20 00:03:08 【问题描述】:

我正在使用 react cytoscape 库。尝试集成到 cytoscape 的 popper 插件。 popper“content”属性期望返回一个div元素,描述附加到“body”元素的popper。 由于上下文提供者位于根元素下,因此该 div 不能成为该上下文的消费者。 如何在根外部定义的 popper 元素中使用相同的上下文。

使用 cytoscape 的 react 组件,但 cytoscape 的插件是纯 js 的。

<body>
 <div id=root>
  <Style_Provider>
      .
      .
      .
  </Style_Provider>
 </div>
 <div id="popper">
    // need to access to style context
 </div>
</body>

【问题讨论】:

popper 强制我将它附加到“Body”。那么,您知道如何在该限制下访问样式上下文 不确定,但可能想在 react 中查看门户 @EricHasselbring - 门户完全解决了这个问题,不错! 你有没有让这个工作?我无法将 Popper 插件与 react-cytoscape 集成。具体来说,Cytoscape.use(Popper) 会抛出一个错误,指出目标未定义。 【参考方案1】:

作为Eric Hasselbring said,portals 解决这个用例:

门户提供了一种一流的方式来将子级呈现到存在于父组件的 DOM 层次结构之外的 DOM 节点中。

这是一个使用上下文的示例:

const ExampleContext = React.createContext(
    "default context"
);

class Example extends React.Component 
    render() 
        return (
            <ExampleContext.Provider value="context from Example">
              <div>
                  This is the parent comnponent.
                  <MyPortal />
              </div>
            </ExampleContext.Provider>
        );
    


class MyPortal extends React.Component 
    static contextType = ExampleContext;
    render() 
        return ReactDOM.createPortal(
            <div>This is "my portal," context stuff is "this.context"</div>,
            document.getElementById("portal")
        );
    


ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<hr>
<div id="portal"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

在你说的评论中:

popper 动态创建这些“div”。因此,我最初无法创建“MyPortal”组件。

只需根据条件创建门户。这是上面的内容,但有一个按钮来显示/隐藏门户:

const ExampleContext = React.createContext(
    "default context"
);

class Example extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            showPortal: false
        ;
        this.showHideClick = this.showHideClick.bind(this);
    

    showHideClick() 
        this.setState((showPortal) => (showPortal: !showPortal));
    

    render() 
        const showPortal = this.state;
        return (
            <ExampleContext.Provider value="context from Example">
              <div>
                  This is the parent comnponent.
                  <input type="button" value=showPortal ? "Hide" : "Show" onClick=this.showHideClick/>
                  showPortal && <MyPortal />
              </div>
            </ExampleContext.Provider>
        );
    


class MyPortal extends React.Component 
    static contextType = ExampleContext;
    render() 
        return ReactDOM.createPortal(
            <div>This is "my portal," context stuff is "this.context"</div>,
            document.getElementById("portal")
        );
    


ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<hr>
<div id="portal"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

【讨论】:

popper 会动态创建这些“div”。因此,我最初无法创建“MyPortal”组件。 @cryptoun - 你不必这样做。只要在合适的时候做。我在上面添加了一个使其有条件的示例。

以上是关于是否可以将反应上下文注入到反应根之外的div(在主体下)的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应中导入根路径之外的组件?

来自库的反应上下文未在消费者中更新

如何使用 fs 与电子反应?

未捕获的错误:在路由器上下文之外呈现的 <Link> 无法导航。(…)反应

vuejs 组件中 props 的深度反应性

可以在本机反应中检测到视图组件吗?