モーダルの作成を通じて、Reactの基本的な機能を学ぶ

## 初めに

Webページを作る際に、モーダルは良く使われるUIの一つかと思いますが、いざ作るとなると案外面倒くさかったりします。

Reactで開発していると、モーダルを実装する際には、[react-modal](https://github.com/reactjs/react-modal)が手軽に実装出来て、良いのですが、学習の題材として、本記事ではライブラリに頼らず、`useState`の機能を使って、実装してみたいと思います。

## 対象読者

React初学者
(本記事で、propsの扱い方とuseStateの使い方が学習できるかと思います)

## ① ベースを作成

まず、AppコンポーネントとModalコンポーネントを作成しましょう。Appコンポーネントにはボタンをクリックした際に、Modalが立ち上がるようButtonを追記しておきましょう。


```react:App.jsx
import React from "react";

const App = () => {
  return <>
  <h2>Modal実装</h2>
  <button>Open Modal</button>
  </>;
};

export default App;
```

続いて、Modalコンポーネントは以下の通り

```react:Modal.jsx
import React from "react";

const Modal = () => {
  return (
    <>
      <div id="overlay">
        <div id="modalContent">
          <p>This is ModalContent</p>
          <button>Close</button>
        </div>
      </div>
    </>
  );
};

export default Modal;
```

## 表示・非表示の制御はuseStateを使用する

次にAppコンポーネントのボタンをクリックした際に、モーダルを表示させるためのflagを定義しましょう。ここで、`useState`を使用します。これでコンポーネント内の状態を管理します。

```react:App.jsx
import React, { useState } from "react";
import Modal from "./components/Modal"; //Modalコンポーネントをimportする

const App = () => {
  const [showModal, setShowModal] = useState(false); // Modalコンポーネントの表示の状態を定義する

  return (
    <>
      <h2>Modal実装</h2>
      <button>Open Modal</button>
      {/* Appコンポーネントから子であるModalコンポーネントにpropsを渡す */}
      <Modal showFlag={showModal} />
    </>
  );
};

export default App;
```

上記で親から子に渡した`showFlag`の状態をみて、ModalコンポーネントはModalの表示・非表示を管理します。注意してほしいのは、**親から子コンポーネントにpropsとして渡してあげる必要があります。**(ここでは、showFlagとして定義)

Modalコンポーネントの実装は以下の通り。親から受け取ったpropsで表示・非表示を判定します。

```react:Modal.jsx
import React from "react";

const Modal = (props) => {
  return (
    <>
      {props.showFlag ? ( // showFlagがtrueだったらModalを表示する
        <div id="overlay">
          <div id="modalContent">
            <p>This is ModalContent</p>
            <button>Close</button>
          </div>
        </div>
      ) : (
        <></>// showFlagがfalseの場合はModalは表示しない
      )}
    </>
  );
};

export default Modal;

```

## クリックイベントを定義

ボタンを押下した際に、showModalの状態を変更する処理を書いていきましょう。onClickイベントを定義して、`showModal`の値を切り替えられるようにしましょう。

```react:app.jsxに以下メソッドを追記
const ShowModal = () => {
  setShowModal(true);
};

<button onClick={ShowModal}>Open Modal</button>
```

Modalコンポーネントのcloseボタンを押した際にはshowModalのstateをfalseにしてあげて、Modalを非表示にしましょう。

ここでも注意が必要です。**ただ単純にCloseのボタンのonClickイベントに以下メソッドを定義しても、`ReferenceError`がコンソールに表示される**と思います。Modalコンポーネントには、**setShowModalが定義されていないため、当然実行することが出来ません。**

```react:Modal.jsx(以下のような実装はReferenceErrorとなる)
<button onClick={() => setShowModal(false)}>Close</button>
```

では、どうするかというとここでも、親から子にpropsとして渡してあげる必要があります。以下の通りです。

```react:app.jsx
<Modal showFlag={showModal} setShowModal={setShowModal} />
```

```react:modal.jsx
const closeModal = () => {
  props.setShowModal(false);
};

<button onClick={closeModal}>Close</button>
```

以上で動作の部分は出来ました。
![forqiita.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/f5e2fc47-58d1-8721-fa4c-bb0f233c787b.gif)

## Modal内の文言を親コンポーネントで定義する。
現状では、Modal内の文言はベタ書きになっています。これを、親コンポーネント側で制御できるようにしましょう。これもpropsを親から子に渡してあげるだけです。

```react:App.jsx
<Modal showFlag={showModal} setShowModal={setShowModal} content="親から渡された値です。" />
```

```react:Modal.jsx
//<p>This is ModalContent</p>
//以下に書き換える
<p>{props.content}</p>
```


## 最後にスタイルを定義する。

簡易的な方法になりますが、Modalコンポーネント内に以下のようにスタイルを定義して、style属性にstyleを定義したオブジェクトを渡してあげましょう。

```css
  const modalContent = {
    background: "white",
    padding: "10px",
    borderRadius: "3px",
  };

  const overlay = {
    position: "fixed",
    top: 0,
    left: 0,
    width: "100%",
    height: "100%",
    backgroundColor: "rgba(0,0,0,0.5)",

    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  };
```

```react:modal.jsx:style属性にstyleを定義したオブジェクトを渡す
<div id="overlay" style={overlay}>
  <div id="modalContent" style={modalContent}>
    <p>{props.content}</p>
    <button onClick={closeModal}>Close</button>
  </div>
</div>
```
![forqiita2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/ff79db6e-c58c-9545-5b8a-b9388f218016.gif)


## 最後に
以上、Reactでのモーダルの実装方法でした。Reactで良く使われる`useState`やpropsの渡し方などの基礎は多少学ぶことができたかと思います。