React Portal

  • by Liam Li
  • 0 likes

In React development, createPortal is a powerful API that allows developers to render child nodes to a DOM node that is outside the parent component's DOM hierarchy. This technology is particularly suitable for scenarios where you need to control the placement of child components in the DOM, such as modals, tooltips, and floating menus.

Basic Usage of createPortal

createPortal requires two parameters: the React child element to be rendered and a DOM element, which is the target container for the child element. The syntax is as follows:

createPortal(child, container)
  • child: A React node, i.e., the content you want to render.
  • container: A DOM element that represents the mounting target for the Portal.

Usage Scenarios

  • Modal: Modals often need to break out of the normal document flow and be centrally displayed globally, often accompanied by a background overlay. Using createPortal allows you to render modal content under the body tag, facilitating global control.
  • Tooltips: Tooltips usually dynamically display based on mouse position. Using createPortal can easily implement this behavior without being affected by the position of the parent component.
  • Context Menus: Custom context menus need to be displayed in specific locations. Using createPortal can prevent display issues caused by the overflow property of the parent container.

Example: Creating a Simple Modal

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Modal({ children, onClose }) {
  return ReactDOM.createPortal(
    <div className="modal">
      <div className="modal-content">
        {children}
        <button onClick={onClose}>Close</button>
      </div>
    </div>,
    document.body
  );
}

function App() {
  const [modalVisible, setModalVisible] = useState(false);

  const openModal = () => setModalVisible(true);
  const closeModal = () => setModalVisible(false);

  return (
    <div>
      <button onClick={openModal}>Open Modal</button>
      {modalVisible && <Modal onClose={closeModal}>This is a modal</Modal>}
    </div>
  );
}

export default App;

In this example, we defined a Modal component that takes children and onClose as parameters. This component uses createPortal to render modal content to the modal-root node. Thus, no matter where the Modal component is called from, the rendered content will appear under modal-root, ensuring the modal can overlay other interface elements.

If not mounting to the body node, we can use the ref creation method:

// App.js or other parent Code

import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import Modal from './Modal';  // Assuming your Modal component is separate

function App() {
  const modalRootRef = useRef(null);

  return (
    <div>
      <div ref={modalRootRef}></div> {/* Mounting point for the modal */}
      <Modal modalRootRef={modalRootRef}>Hello, modal!</Modal>
    </div>
  );
}

export default App;

// Modal.js
import React from 'react';
import ReactDOM from 'react-dom';

function Modal({ children, modalRootRef }) {
  return modalRootRef.current ? ReactDOM.createPortal(
    <div className="modal">
      <div className="modal-content">
        {children}
      </div>
    </div>,
    modalRootRef.current
  ) : null;
}

export default Modal;

Performance and Considerations

While createPortal offers great flexibility, it must be used cautiously. Improper use can lead to performance issues, especially when you frequently create and destroy Portals. Additionally, when using Portals, you should also note:

  • Ensure the Portal's mounting node is available throughout the application's lifecycle.
  • Using Portals may lead to some unexpected style inheritance issues because their position in the DOM tree has changed.
Handling Asynchronous Errors in Express with "express-async-errors"
Leveraging Reselect Selectors in Redux for Performance Optimization

Comments

0 Comments