如何创建反向反应门户

Tim*_*rry 4 javascript performance dom reactjs

反应门户让你将 React 子元素渲染到不同的 DOM 元素中,在页面上完全独立的某个地方。

我想做相反的事情:我想在页面上的其他地方渲染一次 DOM 元素,然后根据我的 React 树将其拉入我的 React DOM 输出中。

对此的具体用例是Monaco Editor。这是一个复杂的组件,从头开始渲染成本很高,但更新成本很低。在我的应用程序中,编辑器随着用户打开/关闭不同的内容而出现/消失。这意味着每次打开新内容时,React 都会从头开始创建组件,而创建新编辑器的延迟使该操作比我希望的要慢。

我想渲染一次,将它隐藏在某个地方,然后在需要的时间和地点将其显示在我的 DOM 中的正确位置。我知道我在任何时候都只需要一个实例。

Tim*_*rry 7

最后我建立了一个库来自己做:https : //github.com/httptoolkit/react-reverse-portal

在一个地方渲染你的内容,一次,然后传递它并将它插入到其他地方的 DOM 中,而无需重新渲染。

例子:

import * as portals from 'react-reverse-portal';

const MyComponent = (props) => {
    const portalNode = React.useMemo(() => portals.createPortalNode());

    return <div>
        <portals.InPortal node={portalNode}>
            <MyExpensiveComponent
                myProp={"defaultValue"}
            />
        </portals.InPortal>

        { props.componentToShow === 'component-a'
            ? <ComponentA portalNode={portalNode} />
            : <ComponentB portalNode={portalNode} /> }
    </div>;
}

const ComponentA = (props) => {
    return <div>
        A:
        <portals.OutPortal node={props.portalNode} />
    </div>;
}

const ComponentB = (props) => {
    return <div>
        B:
        <portals.OutPortal
            node={props.portalNode}
            myProp={"newValue"}
            myOtherProp={123}
        />
    </div>;
}
Run Code Online (Sandbox Code Playgroud)