TypeScript + React TailWindで作るシンプルなModalコンポーネント

こんにちは。てぃろです。

今回はReactでモーダルを簡単に追加する方法を紹介します。

Reactでモーダルを作ろうと思うと、便利なライブラリとしてreact-modalというものがあります。

今回はこれを使ってモーダルの実装をしてみます。

動作環境は以下の通りです。

  • react : 17.0.2
  • react-modal : 3.14.4
  • @tailwindcss/forms : 0.3.3

react-modalをインストールする

公式にある通り以下のどちらかのコマンドでインストールできます。

$ npm install --save react-modal
$ yarn add react-modal

ただ、TypeScriptを使う環境ではこれをインストールするだけではビルドできませんでした。これだけではTypeScriptのための型定義が入らないからです。

そこで、以下のコマンドでさらに型定義をインストールします。

npm install --save @types/react-modal

これで実装できるようになりました。早速実装を紹介します。

Modalを実装する

以下はModalとして必要な部分だけ抜き出していますので、このままでは動作しないと思いますが、まず見て下さい。

import React, { useEffect, useState } from 'react';
import Modal from 'react-modal';

export default function AddBus(): JSX.Element {
  const [showModal, setShowModal] = useState<boolean>(false);

  // 削除の実行処理
  const deleteAction = async (docid: string) => {
    …
  };

  // 削除確認のモーダルの表示
  const handleOpenModal = () => {
    setShowModal(true);
  };

  // 削除確認のモーダルで削除ボタン押下時の処理
  const handleDeleteAction = () => {
    deleteAction();
    setShowModal(false);
  };

  // 削除確認のモーダルでキャンセルボタン押下時の処理
  const handleCloseModal = () => {
    setShowModal(false);
  };

  // モーダルを画面中央に表示する用のスタイル
  const customStyles = {
    content: {
      top: '50%',
      left: '50%',
      right: 'auto',
      bottom: 'auto',
      marginRight: '-50%',
      transform: 'translate(-50%, -50%)',
    },
  };

  // 削除モーダル
  const confirmModal = (
    <Modal
      style={customStyles}
      isOpen={showModal} >
      <div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
        <h3
          className="text-lg leading-6 font-medium text-gray-900"
          id="modal-title">
          削除しますか?
        </h3>
        <div className="mt-2">
          <p className="text-sm text-gray-500">
            削除するともとに戻せません。すでに登録されているユーザへの影響を確認して慎重に操作してください。
            <br />
            本当に削除しますか?
          </p>
        </div>
      </div>
      <div className="px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
        <button
          type="button"
          className="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
          onClick={handleDeleteAction}>
          削除する
        </button>
        <button
          type="button"
          className="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
          onClick={handleCloseModal}>
          削除しない
        </button>
      </div>
    </Modal>
  );

  return (
    <>
      …
      {confirmModal}
    </>
  );
}

表示するとこのようになります。

ソースのコメントなど見ていただいてわかる通り、今回は削除操作の確認モーダルを実装してみたのでした。

handleOpenModalは、ここでは呼び出しがないですが、本来はどこか別のコンポーネントから呼び出します。これを呼び出すことでモーダルが開かれます。

このように特に変わったところはないコンポーネントなのですが、ポイントを上げるとすれば、モーダルを画面中央に表示する用のスタイルを定義している部分です。これはreact-modalの公式でも紹介されているスタイル定義です。これがないと、画面上にでかでかとモーダルが出てしまう形になってしまいますので、必ず定義するようにしてください。

その上で、各要素に対してTailwindを使ったスタイルを適用していけばOKです。

Tailwindのスタイルのポイントはここでは説明しませんが、このようにシンプルなスタイルになりますので、一度コピペして使ってみながら自分のほしいスタイルに向けて微調整されてみてはいかがでしょうか。

最後に

今回はTailwindも使ってReactで使えるシンプルなモーダルの実装を紹介しました。

これを使う前にはmaterial-uiを使っていたので、そこにあるコンポーネントをそのまま使えばよかったのですが、今回のように事前に定義されたコンポーネントがない場合の実装を試してみたという結果でした。

material-uiを使っていないだけで、結局フレームワークを使っていることには変わらないのですが、結果としてモーダルの作り方やスタイルの適用方法など今までにない方法を学ぶことができました。

やはりひとつのやり方を極めるのも非常に有用ですが、たまには別のやり方を試してみて見識を広げるのがいいですね。