⚛️ React Q67 / 113

What are portals in React?

AI-Powered Answer ✓ Answered

React Portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. This is particularly useful for components that need to break out of their parent's styling or layout, such as modals, tooltips, and dropdown menus.

What are React Portals?

A portal is a way to render a component's children into a different DOM node than the parent component, while still maintaining the React component tree and event bubbling behavior. This means that a child component rendered via a portal will appear at a different location in the HTML DOM structure, but it will still be a logical child of its parent in the React tree.

Portals are created using ReactDOM.createPortal(child, container), where child is any renderable React child (elements, strings, fragments, etc.), and container is a DOM element (like an element returned by document.getElementById()).

Why use Portals?

The primary reason to use portals is when a child component's visual appearance needs to 'escape' the overflow, z-index, or other styling constraints of its parent component. Common use cases include:

  • Modals and Dialogs: Ensuring they appear on top of all other content without being clipped by parent overflow: hidden styles.
  • Tooltips and Popovers: Positioning them precisely relative to a trigger element, even if the trigger is deep within a constrained parent.
  • Dropdown Menus: Similar to tooltips, preventing them from being cut off by parent styles.

Despite being rendered into a different DOM node, portals maintain the same React component hierarchy. This is crucial because it means that context still flows correctly, and event bubbling (e.g., a click event on a portal child) will still propagate up to its logical React parent, not its actual DOM parent.

Basic Example

First, you need a target DOM element in your index.html (or wherever your main application mounts):

html
<!-- public/index.html -->
<div id="root"></div>
<div id="modal-root"></div>

Then, in your React component:

jsx
import React from 'react';
import ReactDOM from 'react-dom';

const modalRoot = document.getElementById('modal-root');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el
    );
  }
}

function App() {
  const [showModal, setShowModal] = React.useState(false);

  return (
    <div>
      <h1>My Application</h1>
      <p style={{ overflow: 'hidden', height: '100px', border: '1px solid grey' }}>
        Content that might hide a regular modal.
        <button onClick={() => setShowModal(true)}>Show Modal</button>
      </p>

      {showModal && (
        <Modal>
          <div style={{
            position: 'fixed',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            backgroundColor: 'white',
            padding: '20px',
            border: '2px solid black',
            zIndex: 1000
          }}>
            This is a portal modal!
            <button onClick={() => setShowModal(false)}>Close</button>
          </div>
        </Modal>
      )}
    </div>
  );
}

export default App;

Key Considerations

  • Accessibility: When creating modals or dialogs with portals, ensure proper focus management, keyboard navigation, and ARIA attributes (e.g., aria-modal, aria-labelledby) are implemented for an accessible user experience.
  • Styling: Because portal content is rendered outside the parent's DOM, you might need to apply global styles or use CSS-in-JS solutions that target elements regardless of their DOM position.
  • Performance: While generally efficient, creating many portals could theoretically impact performance, but for typical use cases like modals, it's not a concern.

Summary

React Portals are a powerful feature for rendering components outside their parent's DOM subtree without breaking the React component hierarchy or event flow. They are an essential tool for building robust UI elements like modals and tooltips that need to overlay other content cleanly.