Skillversitas

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.