LoginSignup
1
0

More than 3 years have passed since last update.

React基本事項の備忘録③

Posted at

はじめに

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

モーダルウィンドウの表示

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

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

ディレクトリ構造
React
|-
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;
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の定義

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. 変数を用意する

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

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

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が複数行になる場合は( )でくくって記述します。

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とします。

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;

以上です!

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