Step-by-Step Guide to Implementing React createPortal for Better UI

AqirAqir
3 min read

createPortal lets you render some children into a different part of the DOM.

<div>
  <SomeComponent />
  {createPortal(children, domNode, key?)}
</div>

createPortal(children, domNode, key?)

To create a portal, call createPortal, passing some JSX, and the DOM node where it should be rendered:

import { createPortal } from 'react-dom';
<div>
  <p>This child is placed in the parent div.</p>
  {createPortal(
    <p>This child is placed in the document body.</p>,
    document.body
  )}
</div>

Parameters

  • children: Anything that can be rendered with React, such as a piece of JSX (e.g. <div /> or <SomeComponent />), a Fragment (<>...</>), a string or a number, or an array of these.

  • domNode: Some DOM node, such as those returned by document.getElementById(). The node must already exist. Passing a different DOM node during an update will cause the portal content to be recreated.

  • optional key: A unique string or number to be used as the portal’s key.

Returns

createPortal returns a React node that can be included into JSX or returned from a React component. If React encounters it in the render output, it will place the provided children inside the provided domNode.

Caveats

  • Events from portals propagate according to the React tree rather than the DOM tree. For example, if you click inside a portal, and the portal is wrapped in <div onClick>, that onClick handler will fire. If this causes issues, either stop the event propagation from inside the portal, or move the portal itself up in the React tree.

Usage

Rendering to a different part of the DOM

Portals let your components render some of their children into a different place in the DOM. This lets a part of your component “escape” from whatever containers it may be in. For example, a component can display a modal dialog or a tooltip that appears above and outside of the rest of the page.

To create a portal, render the result of createPortal with some JSX and the DOM node where it should go:

import { createPortal } from 'react-dom';
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>
);}

Rendering a modal dialog with a portal

You can use a portal to create a modal dialog that floats above the rest of the page, even if the component that summons the dialog is inside a container with overflow: hidden or other styles that interfere with the dialog.

In this example, the two containers have styles that disrupt the modal dialog, but the one rendered into a portal is unaffected because, in the DOM, the modal is not contained within the parent JSX elements.

//App.js
import NoPortalExample from './NoPortalExample';
import PortalExample from './PortalExample';

export default function App() {
  return (
    <>
      <div className="clipping-container">
        <NoPortalExample  />
      </div>
      <div className="clipping-container">
        <PortalExample />
      </div>
    </>
  );
}
//NoPortalExample.jsx
import ModalContent from './ModalContent.js';

export default function NoPortalExample() {
  const [showModal, setShowModal] = useState(false);
  return (
    <>
      <button onClick={() => setShowModal(true)}>
        Show modal without a portal
      </button>
      {showModal && (
        <ModalContent onClose={() => setShowModal(false)} />
      )}
    </>
  );
}
//PortalExample.jsx
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
      )}
    </>
  );
}
//ModelContent.jsx
export default function ModalContent({ onClose }) {
  return (
    <div className="modal">
      <div>I'm a modal dialog</div>
      <button onClick={onClose}>Close</button>
    </div>
  );
}
4
Subscribe to my newsletter

Read articles from Aqir directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aqir
Aqir

My skill set reads like a tech enthusiast's wishlist, encompassing mastery in JavaScript, React JS, and a keen proficiency in testing frameworks such as Jest and RTL. With a creative flair backed by hands-on experience, I've woven intricate web applications using Ruby on Rails and ensured their robustness with RSpec. My comfort with databases extends to PostgreSQL and MongoDB, and I navigate complex data structures with ease.My journey as a software craftsman is enriched by a Bachelor's degree in Computer Science from Kurukshetra University, a testament to my commitment to knowledge and growth. My work history boasts contributions that reflect my dedication to delivering cutting-edge solutions.I'm not just a Software Engineer; I'm an architect of digital experiences. Let's connect and explore how my expertise can bring unparalleled value to your projects. Open to exciting opportunities that align with my passion for innovation and drive for excellence.