Использовать Порталы из библиотеки react-dom
:
Порталы предоставляют первоклассный способ визуализации дочерних элементов в узле DOM, который существует вне иерархии DOM родительского компонента.
const HeaderPortal = ReactDOM.createPortal(<Header />, document.getElementById('header'))
const SideBarPortal = ReactDOM.createPortal(<SideBar />, document.getElementById('sidebar'))
const store = createStore(/* ... */)
ReactDOM.render(
<YourDataStoreProvider store={store}>
<HeaderPortal />
<SideBarPortal />
</YourDataStoreProvider>,
document.getElementById('root') // assuming you have an empty "dummy" node with that id
);
Просто визуализируйте ваше приложение в контейнере в любом месте вашего DOM или создайте новый "фиктивный" узел. В моем примере я предполагаю, что есть пустой узел с идентификатором root
. Затем визуализируйте ваши другие компоненты в портал.
Работает ли магазин с избыточностью между разными ReactDOM?
Ваше приложение будет работать так, как если бы оно было полностью отображено в одном контейнере. Если вы используете Portals, ваши компоненты будут находиться в одном и том же дереве компонентов, имеющем тот же контекст, в то время как они будут отображаться где-то еще.
Должен ли я использовать порталы?
Использование Порталов обычно предназначено для использования с компонентами, которые визуально должны «вырваться» из своего контейнера, такими как модалы или диалоги. Но вы также можете использовать их для создания компонентов, похожих на виджеты, которые можно отображать где угодно.
Создание общего компонента портала
Вы также можете создать общий компонент <Portal>
, который создает портал с заданным контейнером id
:
import {createPortal} from 'react-dom';
const Portal = ({children, container}) => createPortal(
children,
document.getElementById(container),
);
export default Portal;
И используйте это так:
ReactDOM.render(
<YourDataStoreProvider store={store}>
<Portal container="header">
<Header />
</Portal>
<Portal container="sidebar">
<SideBar />
</Portal>
</YourDataStoreProvider>,
document.getElementById('root')
);
EDIT
Вам нужен один узел в DOM, где вы можете визуализировать свое приложение. Это может быть новый элемент DOM, который вы создаете, или это может быть один из контейнеров, которые у вас уже есть. Учитывая, что вы используете компонент <Portal>
сверху, он также может выглядеть так:
ReactDOM.render(
<YourDataStoreProvider store={store}>
<Header /> // this will be visible in your header container
<Portal container="sidebar">
<SideBar /> // this will be rendered to the sidebar container
</Portal>
</YourDataStoreProvider>,
document.getElementById('header')
);
Это сделает ваше приложение в контейнере header
. Но только ваш <Header>
компонент фактически будет иметь представление DOM в этом контейнере. Боковая панель будет отображаться в контейнере sidebar
порталом. Но они по-прежнему будут использовать одно и то же дерево реагирующих компонентов и иметь одного и того же поставщика магазина.