← Back to list

Building My Own React Component Library — Part 1: The Portal

Why Build a Component Library?

Akshat Tiwari in JavaScript in Plain English · 2025-07-06 18:58 · 22 claps · 2.4 min read
#react #reactjs #react-components #react-component-library #component-libraries
Open on Medium ↗
Wiki topics: PRD · Product Design 🌐 · Web Development 📚 · Books & Reading

Building My Own React Component Library — Part 1: The Portal

Why Build a Component Library?

Every frontend developer has, at some point, reached for UI libraries like Material-UI, Chakra, or Ant Design. They’re fantastic — until you hit customization limits, bundle size concerns, or just want full control. That’s why I decided to build Reactive, my own component library from scratch.

In this first installment, we’ll dive into one of React’s most powerful yet underappreciated features: Portals. These will become the backbone for modals, tooltips, and other “escape hatch” components in the library.

Want to follow along? Star the Reactive GitHub repo and code with me!

The Problem: Why Portals?

Imagine you’re building a modal. Normally, you’d render it inside your component tree:

function App() {
  return (
    <div className="app">
      <Navbar />
      <Modal /> {/* Renders deep inside the DOM */}
    </div>
  );
}

But this causes two big problems:

  1. Z-Index Wars: If any parent has overflow: hidden or z-index, your modal gets clipped or buried.
  2. Accessibility Nightmares: Screen readers might not properly announce content nested in complex UIs.

Portals solve this by letting you render components outside the React root, while keeping them logically inside your component tree.

How Portals Work: Breaking the DOM Hierarchy

React’s createPortal lets you render a component anywhere in the DOM while preserving:

  • Event bubbling (clicks inside the portal behave as if they came from the React tree)
  • Context access (the portal can still consume React context)

Here’s the magic in action:

<body>
  <div id="root">   <!-- Your React app -->
    <App />         <!-- Modal *logic* lives here -->
  </div>
  <div id="portal-root"></div>  <!-- Modal *DOM* renders here! -->
</body>

The modal’s logic stays in your component (for props/state), but its DOM jumps to portal-root, escaping CSS containment.

Building the Portal Component

Let’s implement this properly. Our Portal will:

  1. Auto-create a DOM container if missing.
  2. Clean up after itself when unmounted.
  3. Work seamlessly with SSR (no document errors).
  4. Here’s the final code (explained below):
import { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import Props from 'prop-types';

function Portal({children, containerId='portal-root'}){

    const [portalElement, setPortalElement]=useState(null);

    useEffect(()=>{

        let portalElement=document.getElementById(containerId);
        let systemGenerated=false;

        if(!portalElement){
            systemGenerated=true;
            portalElement=document.createElement('div');
            portalElement.id=containerId;
            document.body.appendChild(portalElement);
        }

        setPortalElement(portalElement);

        return ()=>{
            if(systemGenerated){
                document.body.removeChild(portalElement);
            }
        }

    },[containerId]);

    if(!portalElement)  return null;

    return ReactDOM.createPortal(children,portalElement);
}

Portal.propTypes = {
 children : Props.object,
 containerId: Props.string
}

export default Portal;

Using the Portal for Modals

Next time, we’ll use this Portal to build an accessible, keyboard-trapped modal. Here’s a sneak peek:

function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;
  return (
    <Portal>
      <div className="modal-overlay">
        <div className="modal-content">
          {children}
          <button onClick={onClose}>Close</button>
        </div>
      </div>
    </Portal>
  );
}

This modal will:

  • Auto-focus when opened.
  • Trap keyboard navigation inside.
  • Close on Escape key.

Let’s Build Together!

This is just the start. Reactive will grow to include:

  • Modals
  • Tooltips
  • Notifications
  • And more — all with zero dependencies!

👉 Star the GitHub repo to follow along.

Next time, we’ll enhance our Portal with TypeScript and build the modal component. Drop your questions below—I’ll answer them in the next post!

Happy coding!

Thank you for being a part of the community

Before you go:


메타데이터
post_id
5e76e7625130
slug
building-my-own-react-component-library-part-1-the-portal-5e76e7625130
url
https://javascript.plainenglish.io/building-my-own-react-component-library-part-1-the-portal-5e76e7625130
canonical_url
https://javascript.plainenglish.io/building-my-own-react-component-library-part-1-the-portal-5e76e7625130
author_url
https://medium.com/@akshatmtiwari
status
ok
fetched_at
2026-06-22 17:31:34