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】react-modalで複数のモーダルの作り方

Posted at

はじめに

rect-modalで複数のモダールを制御するやり方が分からなかったので記事にします。

react-modalは、Reactアプリケーションで簡単にモーダルウィンドウを作成できるライブラリです。モーダルの開閉をisOpenプロパティで制御します。

警告
本記事では、react-modalのインストールが完了している前提で進めます。
以下のコマンドで事前にインストールしてください

$ npm install --save react-modal

実装方法

モーダルが1つの場合

App.jsx
import { useState } from "react";
import "./App.css";
import NormalModal from "./components/NormalModal";

function App() {
  const [modalIsOpen, setisOpen] = useState(false);
  
  return (
    <>
      <div className="bg-teal-500 h-screen p-20">
        <h1 className="text-3xl font-bold underline text-center mb-8">モーダル練習</h1>
        <NormalModal modalIsOpen={modalIsOpen} setisOpen={setisOpen}>
          aaaa
        </NormalModal>
      </div>
    </>
  );
}

export default App;
NormalModal.jsx
import Modal from "react-modal";

const NormalModal = ({ setisOpen, modalIsOpen, children }) => {
  return (
    <div>
      <Modal isOpen={modalIsOpen}>
        <button onClick={() => setisOpen((prev) => !prev)}>モーダルを閉じる</button>
        <div>{children}</div>
      </Modal>
      <button onClick={() => setisOpen((prev) => !prev)}>モーダルを開く</button>
    </div>
  );
};

export default NormalModal;

画面収録 2024-12-07 11.gif
このように簡単にモーダルを実装することができます。

モーダルが2つの場合

ページ内にモーダルが一つの場合は上記のように実装すれば良いですが、ページの中で複数のモーダルがあることが多いと思います。いくつかの方法で試してみました。

モーダルのコンポーネントを2つにしてみる

まずはモーダルを増やしてみました。
1つ目のモーダルには「aaaaa」が表示され2つ目のモーダルには「bbbb」が表示されていれば正しい挙動です。

NormalModal.jsx
import { useState } from "react";
import "./App.css";
import NormalModal from "./components/NormalModal";

function App() {
  const [modalIsOpen, setisOpen] = useState(false);
  return (
    <>
      <div className="bg-teal-500 h-screen p-20">
        <h1 className="text-3xl font-bold underline text-center mb-8">モーダル練習</h1>
        <NormalModal modalIsOpen={modalIsOpen} setisOpen={setisOpen}>
          aaaa
        </NormalModal>
        <!-- コンポーネントを追加 -->
        <NormalModal modalIsOpen={modalIsOpen} setisOpen={setisOpen}>
          bbbb
        </NormalModal>
        <!-- /コンポーネントを追加 -->
      </div>
    </>
  );
}

export default App;

画面収録 2024-12-07 11.gif

このGIFでは、NormalModalを2つ表示していますが、1つのstateで管理しているため、どちらをクリックしても2つ同時に開閉してしまいます。今の状態ではどのモーダルをクリックしたのか判定はできないということがわかりました。

モーダルのごとに個別のstateで管理する

現在はモーダルの開閉状態を一つのstateで管理しています。モーダルごとに個別に管理してみました。

App.jsx
import { useState } from "react";
import "./App.css";
import NormalModal from "./components/NormalModal";

function App() {
  <!-- stateをモーダルごとに変更 -->
  const [modalIsOpenA, setisOpenA] = useState(false);
  const [modalIsOpenB, setisOpenB] = useState(false);
  <!-- /stateをモーダルごとに変更 -->

  return (
    <>
      <div className="bg-teal-500 h-screen p-20">
        <h1 className="text-3xl font-bold underline text-center mb-8">モーダル練習</h1>
        <NormalModal isOpen={modalIsOpenA} setisOpen={setisOpenA}>
          aaaa
        </NormalModal>
        <NormalModal isOpen={modalIsOpenB} setisOpen={setisOpenB}>
          bbbb
        </NormalModal>
      </div>
    </>
  );
}

export default App;

画面収録 2024-12-07 12.gif

stateをモーダルごとに管理するように変更するとモーダルの出しわけをすることに成功しました。

モーダルのごとに個別のidで管理する

モーダルの出しわけに成功しました。しかしモーダルの数が増えていくたびに固有のstateを作るのは現実的でないのでidを使って管理するようにしてみました。

App.jsx
import { useState } from "react";
import "./App.css";
import NormalModal from "./components/NormalModal";

function App() {
  const [openModalId, setOpenModalId] = useState(null);

  return (
    <>
      <div className="bg-teal-500 h-screen p-20 relative">
        <h1 className="text-3xl font-bold underline text-center mb-8">モーダル練習</h1>
        <NormalModal modalId="modal1" openModalId={openModalId} setOpenModalId={setOpenModalId}>
          aaaa
        </NormalModal>
        <NormalModal modalId="modal2" openModalId={openModalId} setOpenModalId={setOpenModalId}>
          bbbb
        </NormalModal>
        <NormalModal modalId="modal3" openModalId={openModalId} setOpenModalId={setOpenModalId}>
          cccc
        </NormalModal>
      </div>
    </>
  );
}

export default App;

NormalModal.jsx
import Modal from "react-modal";

const NormalModal = ({ setOpenModalId, openModalId, children, modalId }) => {
  const isOpen = openModalId === modalId;
  return (
    <div>
      <Modal isOpen={isOpen}>
        <button onClick={() => setOpenModalId(null)}>モーダルを閉じる</button>
        <div>{children}</div>
      </Modal>
      <button onClick={() => setOpenModalId(modalId)}>モーダルを開く</button>
    </div>
  );
};

export default NormalModal;

画面収録 2024-12-07 15.gif

このように開いているモーダルのidを状態として管理することによって複数のモーダルを制御することができました。

終わりに

本記事では、react-modalを使った基本的なモーダル実装から、複数モーダルを効率的に管理する方法を記事にしました。

今回の実装方法を応用することで、より複雑なモーダル構成も管理しやすくなると思います。

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?