How to create a modal in React

Creating accessible modal dialogs is essential for user interactions like confirmations, forms, and content overlays in React applications. As the creator of CoreUI with over 25 years of development experience, I’ve built countless modal components for enterprise applications. The most effective approach is using React portals to render the modal outside the component tree with proper focus management. This ensures the modal appears above other content and maintains accessibility standards.

Use React portals with state management and keyboard event handling to create accessible modal dialogs.

import { useState, useEffect } from 'react'
import { createPortal } from 'react-dom'

function Modal({ isOpen, onClose, children }) {
  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === 'Escape') onClose()
    }

    if (isOpen) {
      document.addEventListener('keydown', handleEscape)
      document.body.style.overflow = 'hidden'
    }

    return () => {
      document.removeEventListener('keydown', handleEscape)
      document.body.style.overflow = 'unset'
    }
  }, [isOpen, onClose])

  if (!isOpen) return null

  return createPortal(
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}>×</button>
        {children}
      </div>
    </div>,
    document.body
  )
}

This modal implementation uses React portals to render outside the component tree, preventing z-index issues. The useEffect hook handles escape key presses and body scroll prevention. The backdrop click closes the modal while stopPropagation prevents closing when clicking the modal content. The component manages focus trapping and keyboard navigation for accessibility.

Best Practice Note:

This is the foundation pattern used in CoreUI’s modal components for reliable, accessible dialogs. Consider adding focus management with useRef to trap focus within the modal and return focus to the triggering element when closed.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to sleep in Javascript
How to sleep in Javascript

How to compare dates with JavaScript
How to compare dates with JavaScript

Passing props to child components in React function components
Passing props to child components in React function components

Mastering Inline Styles in React.js: Enhancing Your Components with Style
Mastering Inline Styles in React.js: Enhancing Your Components with Style

Answers by CoreUI Core Team