DEV Community

poshiya parth s
poshiya parth s

Posted on

Using React Portals to Render Elements Anywhere in the DOM

Introduction
React Portals provide a powerful way to render components outside the main DOM hierarchy, allowing for greater flexibility in placing elements. This is particularly useful for creating modals, tooltips, and other components that need to be rendered at a different location in the DOM. In this guide, we will demonstrate how to use React Portals to open and render elements anywhere in your application.

Prerequisites
Before we begin, ensure you have a basic understanding of React and functional components. Familiarity with hooks (useState, useEffect) will be beneficial.

Step 1: Setting Up the Project
First, create a new React project or navigate to your existing project:

npx create-react-app react-portal-tutorial
cd react-portal-tutorial
npm start

Enter fullscreen mode Exit fullscreen mode

Step 2: Creating the Portal Component
Create a new file PortalComponent.js and add the following code to define a reusable portal component:

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

const PortalComponent = ({ children, containerId }) => {
  const container = document.getElementById(containerId);
  return container ? ReactDOM.createPortal(children, container) : null;
};

export default PortalComponent;

Enter fullscreen mode Exit fullscreen mode

Step 3: Adding the Target Element in the DOM
Ensure you have an element in your index.html or another component where the portal can render its content. For instance, add this div in your public/index.html:

<body>
  <div id="root"></div>
  <div id="header-children"></div> <!-- Target Element for Portal -->
</body>

Enter fullscreen mode Exit fullscreen mode

Step 4: Implementing the Portal in Your Component
Create a component, App.js, and use the PortalComponent to render content inside the target element (header-children):

import React, { useState } from 'react';
import PortalComponent from './PortalComponent';

const App = () => {
  const [isSearch, setIsSearch] = useState(false);
  const [isDelete, setIsDelete] = useState(false);

  const handleCancel = () => {
    setIsSearch(false);
    setIsDelete(false);
  };

  const onDeleteClick = () => setIsDelete(true);
  const onSearchClick = () => setIsSearch(true);

  return (
    <div>
      <h1>React Portal Example</h1>
      <button onClick={onSearchClick}>Search</button>
      <button onClick={onDeleteClick}>Delete</button>
      <div id="header-children"></div>
      <PortalComponent containerId="header-children">
        <div className="gap-5 flex">
          {isSearch || isDelete ? (
            <button
              className="text-xl leading-8 font-semibold text-caribbeangreen"
              onClick={handleCancel}
            >
              Cancel
            </button>
          ) : (
            <HistoryActions
              history={history}
              onDeleteClick={onDeleteClick}
              onSearchClick={onSearchClick}
            />
          )}
        </div>
      </PortalComponent>
    </div>
  );
};

const HistoryActions = ({ history, onDeleteClick, onSearchClick }) => (
  <div>
    <button onClick={onSearchClick}>Search History</button>
    <button onClick={onDeleteClick}>Delete History</button>
  </div>
);

export default App;

Enter fullscreen mode Exit fullscreen mode

Step 5: Styling the Portal Content
Add necessary styles in your index.css or another CSS file:

.gap-5 {
  gap: 1.25rem;
}

.flex {
  display: flex;
}

.text-caribbeangreen {
  color: #00FF7F;
}

.text-xl {
  font-size: 1.25rem;
}

.leading-8 {
  line-height: 2rem;
}

.font-semibold {
  font-weight: 600;
}

Enter fullscreen mode Exit fullscreen mode

Conclusion
In this tutorial, we've covered how to use React Portals to render components outside the main DOM hierarchy. By following these steps, you can create flexible and powerful UI elements that can be rendered anywhere in your application. This technique is especially useful for components like modals, tooltips, and context menus.

first file

const headerChildrenRenderer = document.getElementById("header-children");

  {createPortal(
          <div className="gap-5 flex">
            {isSearch || isDelete ? (
              <button
                className="text-xl leading-8 font-semibold text-caribbeangreen"
                onClick={handleCancel}
              >
                Cancel
              </button>
            ) : (
              <HistroyActions
                history={history}
                onDeleteClick={onDeleteClick}
                onSearchClick={onSearchClick}
              />
            )}
          </div>,
          headerChildrenRenderer as HTMLElement
        )}
Enter fullscreen mode Exit fullscreen mode

second file

// ref for when we want to open above element
        <div id='header-children'></div>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)