「回顾 2022,展望 2023,我正在参与2022 年终总结征文大赛活动」
概念
将子节点渲染到指定的 DOM 节点,还可以当做子组件使用
父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器,例如,对话框、悬浮卡以及提示框
脱离文件流程
使用
<div>
<SomeComponent />
{createPortal(children, domNode, key?)}
</div>
import { createPortal } from 'react-dom';
export default function MyComponent() {
return (
<div style={{ border: '2px solid black' }}>
<p>This child is placed in the parent div.</p>
{createPortal(
<p>This child is placed in the document body.</p>,
document.body
)}
</div>
);
}
modal dialog
import { useState } from 'react';
import { createPortal } from 'react-dom';
import ModalContent from './ModalContent.js';
export default function PortalExample() {
const [showModal, setShowModal] = useState(false);
return (
<>
<button onClick={() => setShowModal(true)}>
Show modal using a portal
</button>
{showModal && createPortal(
<ModalContent onClose={() => setShowModal(false)} />,
document.body
)}
</>
);
}
不是 react 组件内部使用
import { createPortal } from 'react-dom';
const sidebarContentEl = document.getElementById('sidebar-content');
export default function App() {
return (
<>
<MainContent />
{createPortal(
<SidebarContent />,
sidebarContentEl
)}
</>
);
}
function MainContent() {
return <p>This part is rendered by React</p>;
}
function SidebarContent() {
return <p>This part is also rendered by React!</p>;
}
第三方组件库渲染 React 组件
import { useRef, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { createMapWidget, addPopupToMapWidget } from './map-widget.js';
export default function Map() {
const containerRef = useRef(null);
const mapRef = useRef(null);
const [popupContainer, setPopupContainer] = useState(null);
useEffect(() => {
if (mapRef.current === null) {
const map = createMapWidget(containerRef.current);
mapRef.current = map;
const popupDiv = addPopupToMapWidget(map);
setPopupContainer(popupDiv);
}
}, []);
return (
<div style={{ width: 250, height: 250 }} ref={containerRef}>
{popupContainer !== null && createPortal(
<p>Hello from React!</p>,
popupContainer
)}
</div>
);
}
注意
domNode 必须已经存在