Fragments & Portals
The Extra DOM Node Problem
A component must return a single element. We often wrap things in an unnecessary <div>.
React.Fragment
import { Fragment } from 'react';
function TableRow() {
return (
<Fragment>
<td>Name</td>
<td>Age</td>
</Fragment>
);
}
Shorthand: <>...</> — but it cannot receive props (such as key).
Portals
Render a child component to a DOM node outside the parent hierarchy.
import { createPortal } from 'react-dom';
function Modal({ children, isOpen }) {
if (!isOpen) return null;
return createPortal(
<div className="modal-overlay">
<div className="modal-content">{children}</div>
</div>,
document.getElementById('modal-root')
);
}
Portal Use Cases
| Use Case | Reason |
|---|---|
| Modals | Overlay on top of content |
| Tooltips | Float above an element |
| Dropdowns | Clipped by parent overflow |
| Notifications | Corner of the screen |
Usage Example
function App() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Open</button>
<Modal isOpen={open} onClose={() => setOpen(false)}>
<h2>Confirmation</h2>
<button onClick={() => setOpen(false)}>Close</button>
</Modal>
</>
);
}
A Portal still receives events from the React tree even when rendered into a different DOM node. Next chapter: Refs & DOM.