1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactで createPortalを使用したモーダルを作成する方法

Posted at

こんばんは。

今日は「Reactで createPortalを使用したモーダルを作成する方法」について説明いたします。

React で createPortal を使用したモーダルを作成する方法は、React のポータル機能を使って、コンポーネントを DOM の別の場所にレンダリングするものです。モーダルは通常、アプリケーションのルート DOM に直接挿入され、通常のコンテンツとは分離されている必要があるため、このようなポータルを使うのが便利です。

以下は、createPortal を用いたシンプルなモーダルの実装例です。

基本的なModalコンポーネント

Modal.js というコンポーネントを作成し、ポータルを使ってモーダルを別の DOM ノードにレンダリングします。

// Modal.js
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import './Modal.css'; // スタイリング用のCSSファイル

const Modal = ({ isOpen, onClose, children }) => {
  // モーダルが開いていない場合は何も表示しない
  if (!isOpen) return null;

  // モーダルの外をクリックした時に閉じる処理
  const handleClickOutside = (e) => {
    if (e.target.className === 'modal-overlay') {
      onClose();
    }
  };

  // useEffectでエスケープキーを押した時にモーダルを閉じる
  useEffect(() => {
    const handleEsc = (e) => {
      if (e.key === 'Escape') {
        onClose();
      }
    };
    window.addEventListener('keydown', handleEsc);
    return () => window.removeEventListener('keydown', handleEsc);
  }, [onClose]);

  // ポータルを利用してbodyに直接モーダルを描画する
  return ReactDOM.createPortal(
    <div className="modal-overlay" onClick={handleClickOutside}>
      <div className="modal-content">
        <button className="modal-close" onClick={onClose}>
          Close
        </button>
        {children}
      </div>
    </div>,
    document.getElementById('modal-root') // モーダルを表示するためのDOMノード
  );
};

export default Modal;

モーダル用のスタイリング

次に、Modal.css というCSSファイルを作成し、モーダルのスタイルを定義します。

/* Modal.css */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  max-width: 500px;
  width: 100%;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  z-index: 1001;
  position: relative;
}

.modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
}

モーダルを使用する親コンポーネント

App.js にて、モーダルの状態管理と使用方法を記述します。

// App.js
import React, { useState } from 'react';
import Modal from './Modal';

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);

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

  return (
    <div className="App">
      <h1>React Modal with Portal</h1>
      <button onClick={openModal}>Open Modal</button>

      <Modal isOpen={isModalOpen} onClose={closeModal}>
        <h2>This is a Modal</h2>
        <p>Click outside or press Esc to close.</p>
      </Modal>
    </div>
  );
}

export default App;

index.html でモーダル用のノードを追加

React アプリケーションの public/index.html にモーダル用の DOM ノードを追加します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React Modal with Portal</title>
  </head>
  <body>
    <div id="root"></div>
    <div id="modal-root"></div> <!-- モーダル用のポータルルート -->
  </body>
</html>

動作確認

  • 「Open Modal」ボタンをクリックすると、モーダルが表示されます。
  • モーダルの外側をクリックするか、エスケープキーを押すとモーダルが閉じます。

この方法で、createPortal を使って React アプリケーションにモーダルを実装することができます。ポータルを使うことで、モーダルが通常の DOM ツリーの構造に影響を与えずに表示されます。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?