はじめに
rect-modalで複数のモダールを制御するやり方が分からなかったので記事にします。
react-modalは、Reactアプリケーションで簡単にモーダルウィンドウを作成できるライブラリです。モーダルの開閉をisOpen
プロパティで制御します。
警告
本記事では、react-modal
のインストールが完了している前提で進めます。
以下のコマンドで事前にインストールしてください
$ npm install --save react-modal
実装方法
モーダルが1つの場合
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;
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;
モーダルが2つの場合
ページ内にモーダルが一つの場合は上記のように実装すれば良いですが、ページの中で複数のモーダルがあることが多いと思います。いくつかの方法で試してみました。
モーダルのコンポーネントを2つにしてみる
まずはモーダルを増やしてみました。
1つ目のモーダルには「aaaaa」が表示され2つ目のモーダルには「bbbb」が表示されていれば正しい挙動です。
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;
このGIFでは、NormalModal
を2つ表示していますが、1つのstate
で管理しているため、どちらをクリックしても2つ同時に開閉してしまいます。今の状態ではどのモーダルをクリックしたのか判定はできないということがわかりました。
モーダルのごとに個別のstate
で管理する
現在はモーダルの開閉状態を一つのstate
で管理しています。モーダルごとに個別に管理してみました。
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;
state
をモーダルごとに管理するように変更するとモーダルの出しわけをすることに成功しました。
モーダルのごとに個別のid
で管理する
モーダルの出しわけに成功しました。しかしモーダルの数が増えていくたびに固有のstate
を作るのは現実的でないのでidを使って管理するようにしてみました。
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;
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;
このように開いているモーダルのid
を状態として管理することによって複数のモーダルを制御することができました。
終わりに
本記事では、react-modal
を使った基本的なモーダル実装から、複数モーダルを効率的に管理する方法を記事にしました。
今回の実装方法を応用することで、より複雑なモーダル構成も管理しやすくなると思います。