React基本事項の備忘録③

# はじめに
ProgateでReactの第三章も学習を終えたので備忘録としてまとめたいと思います。

## モーダルウィンドウの表示
モーダルウィンドウは、元のウィンドウの上に別枠で表示されるウィンドウのことです。
よくポップアップと混同されがちですが、ポップアップは**表示を目立たせることが目的**なのに対して、モーダルウィンドウは**操作の制御をすることが目的**です。

前回のファイル構成を維持しつつ、新しくモーダルウィンドウに関するコードを追記していきたいと思います。

```php:ディレクトリ構造
React
|-
```

```php:App.js
import React from 'react';
{/* Lesson.jsをインポート */}
import Lesson from './Lesson';

class Main extends React.Component {
  render() {
　　{/* lessonListを定義 */}
    const lessonList = [
      {
        name: 'HTML & CSS',
        image: 'HTML&CSS.png',
        introduction: 'WEBページはHTML、CSSという言語によってその見た目が作られています。',
      },
      {
        name: 'Sass',
        image: 'Sass.png',
        introduction: 'SassはCSSをより便利に効率的にするための言語です。',
      },
      {
        name: 'JavaScript',
        image: 'JavaScript.png',
        introduction: 'JavaScriptはフロントエンドだけでなく、サーバーサイドまで広い可能性を持つプログラミング言語です。',
      },
      {
        name: 'React',
        image: 'React.png',
        introduction: 'ReactはHTMLのように、サイトの見た目をつくることができるJavaScriptのライブラリです。',
      },
    ];

    return (
      <div className='main-wrapper'>
        <div className='main'>
          <div className='copy-container'>
            <h1>Hello, World.</h1>
            <h2>プログラミングの世界へようこそ！</h2>
          </div>
          <div className='lesson-container'>
            <h3>学べるレッスン</h3>
　　　　　　　{/* mapメソッドで繰り返し処理 */}
            {lessonList.map((lessonItem) => {
              return (
                <Lesson
                  name={lessonItem.name}
                  image={lessonItem.image}
　　　　　　　　　　　{/* introductionを追加 */}
                  introduction={lessonItem.introduction}
                />
              );
            })}
          </div>
        </div>
      </div>
    );
  }
}

export default Main;
```

```php:Lesson.js
import React from 'react';

class Lesson extends React.Component {  
  render() {
    return (
      <div className='lesson-card'>
        <div className='lesson-item'>
          <p>{this.props.name}</p>
          <img src={this.props.image} />
        </div>
        {/* 追記部分 */}
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
　　　　　　　　 {/* introductionのpropsを受け取る */}
              <p>{this.props.introduction}</p>
            </div>
            <button className='modal-close-btn'>
              とじる
            </button>
          </div>
        </div>
      </div>
    );
  }
}

export default Lesson;
```
ここまでの記述でモーダルウィンドウの表示はできているのですが、画面に常に表示されてしまいます。なので表示/非表示を切り替える必要があります。

これを`state`を用いて切り替えていきます。
具体的には`isModalOpen`という真偽値型のstateを用意しtureのときには表示、falseのときは非表示というように設定します。
まずはstateを定義します。

### stateの定義

```php:Lesson.js
import React from 'react';

class Lesson extends React.Component {
  // constructorを定義
  constructor(props) {
    super(props);
    // stateの初期値を定義
    this.state = {isModalOpen:false};
    
  }
```

### stateの表示
考え方としては`isModalOpen`がtrueのときはLesson.jsにモーダルのJSXが存在し、falseのときは存在しないという方針で記述していきます。手順は以下の通りです。

**1. 変数を用意する**
**2. if文で`もしisModalOpenがtrueだったら`という条件分岐を記述**
**3. モーダルのJSXを記述**

#### 1. 変数を用意する

```php:Lesson.js
render (){
  {/* カラの変数であるmodalを定義 */}
  let modal;
}
```

#### if文で`もしisModalOpenがtrueだったら`という条件分岐を記述

```php:Lesson.js
constructor(props) {
    super(props);
    // stateの初期値を定義
    this.state = {isModalOpen:false};
}
render (){
  {/* カラの変数であるmodalを定義 */}
  let modal;
  {/* 条件分岐 */}
  if (this.state,isModalOpen)
}
```

#### モーダルのJSXを記述
カラの変数modalにJSXを代入します。
tureのときはreturn内に変数modalを表示させます。

ルールとして変数に代入するJSXが複数行になる場合は`( )`でくくって記述します。

```php:Lesson.js
  constructor(props) {
    super(props);
    this.state = {isModalOpen: false};
  }

  render() {
    // 変数modalを定義
    let modal;
    
    // if文を用意
    if(this.state.isModalOpen) {
      {/* modalの中身は　( ) でくくる */}
      modal = (
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
              <p>{this.props.introduction}</p>
            </div>
            <button className='modal-close-btn'>
              とじる
            </button>
          </div>
        </div>
      )
　　　　return (
     　　 <div className='lesson-card'>
        　　<div className='lesson-item'>
          　　<p>{this.props.name}</p>
          　　<img src={this.props.image} />
        　　</div>
        　　{/* 変数モーダルを表示 */}
       　　 {modal}
      　　</div>
    　);
    }
```
ここまでで、条件分岐により表示/非表示の切り替えができました。
次にonClickイベントを用いてtrueとfalseを切り替えるコードを記述します。

モーダルウィンドウを表示する関数を`handleClickOpen`
モーダルウィンドウを非表示にする関数を`handleClickClose`とします。

```php:Lesson.js
import React from 'react';

class Lesson extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isModalOpen: false};
  }
　 // handleClickOpen関数を定義
  handleClickOpen () {
    this.setState({isModalOpen: true});
  }
  
  // handleClickClose関数を定義
  handleClickClose () {
    this.setState({isModalOpen:false});
  }

  render() {
    let modal;
    if (this.state.isModalOpen) {
      modal = (
        <div className='modal'>
          <div className='modal-inner'>
            <div className='modal-header'></div>
            <div className='modal-introduction'>
              <h2>{this.props.name}</h2>
              <p>{this.props.introduction}</p>
            </div>
            {/* onClickイベントを追加 */}
            <button
              className='modal-close-btn'
              onClick={() => {this.handleClickClose()}}
            >
              とじる
            </button>
          </div>
        </div>
      );
    }

    return (
      <div className='lesson-card'>
        <div
          className='lesson-item'
          {/* onClickイベントを追加 */}
          onClick={() => {this.handleClickLesson()}}
        >
          <p>{this.props.name}</p>
          <img src={this.props.image} />
        </div>
        {modal}
      </div>
    );
  }
}

export default Lesson;
```

以上です！