Reactでモーダル表示をする。

作ったもの

こんなサイトをReactで作ってみました(画像はgoogle検索で出てきたものを使用しました)。

Progateを大いに参考にしました。

f:id:khirok:20200113151132p:plain


それぞれの画像をクリックすると、こんなモーダルが用事されます。

f:id:khirok:20200113151224p:plain

とじるボタンを押すと元の画面に戻ります。

 

App.js

 import React from 'react';
 import Header from './Header';
 import Main from './Main';
 import Footer from './Footer'
 import './App.css';

 class App extends React.Component {
  render() {
   return (
    <div>
     <Header/>
     <Main/>
     <Footer/>
    </div>
  );
 }
 }

 export default App;

 

 

 最初にHeader.js、Main.js、Footer.js、App.cssを読み込んでいます。

import Header from './Header';
import Main from './Main';
import Footer from './Footer'
import './App.css';

 

Appのクラス内で、Header.js、Main.js、Footer.jsを表示させています。

class App extends React.Component {
render() {
return (
<div>
<Header/>
<Main/>
<Footer/>
</div>
);
}
}

Main.js

import React from 'react';
import City from './City';

class Main extends React.Component {
 render() {
 const citylist = [
 {
  name: 'パリ',
       9d5b-a9da6d0a508d_m.jpg',
  introduction: '芸術の都 パリ'
 },
 {
  name: 'ロンドン',
  introduction: 'イギリスの首都'
 },
 {
  name: 'ベルリン',
  introduction: 'ドイツの首都'
 },
 {
  name: 'ローマ',
       centre-of-rome-01.jpg',
  introduction: 'イタリアの首都'
 },
 ];

return (
  <div className='main-wrapper'>
   <div className='main'>
    <div className='title-container'>
     <h2>ヨーロッパの4都市を紹介!</h2>
    </div>
    <div className='city-container'>
     {citylist.map((CityItem) => {
      return (
       <City
        name={CityItem.name}
        image={CityItem.image}
        introduction={CityItem.introduction}
       />
      );
     })}
     </div>
   </div>
 </div>
 )
}
}

export default Main;

 

最初にCity.jsを読み込んでいます。

import City from './City';

 

Mainクラスの中では定数citylistを定義し、4つの都市の情報を配列に格納しています。

 const citylist = [
 {
  name: 'パリ',
      da6d0a508d_m.jpg',
  introduction: '芸術の都 パリ'
 },
 {
  name: 'ロンドン',
  introduction: 'イギリスの首都'
 },
 {
  name: 'ベルリン',
  introduction: 'ドイツの首都'
 },
 {
  name: 'ローマ',
      -rome-01.jpg',
  introduction: 'イタリアの首都'
 },
];

 

city-containerの中では、mapメソッドを用いてcitylistの情報をCityItemとして取り出し、name、image、introductionに代入しています。

その情報を持ったCity.jsを表示させています。

 <div className='city-container'>
  {citylist.map((CityItem) => {
   return (
    <City
     name={CityItem.name}
     image={CityItem.image}
     introduction={CityItem.introduction}
    />
   );
  })}
 </div>

 

City.js

import React from 'react';

class City extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}

handleClickCity() {
this.setState({isModalOpen: true});
}

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>
   <button
    className='modal-close-btn'
    onClick={() => this.handleClickClose()}
   >
     とじる
   </button>
  </div>
 </div>
);
}
return(
  <div className='city-card'>
   <div
    className='city-item'
    onClick={() => {this.handleClickCity()}}
   >
    <p>{this.props.name}</p>
    <img src={this.props.image} />
   </div>
   {modal}
  </div>
 );
 }
}


export default City;

 

Cityクラスの中では、まず

 constructor(props) {
  super(props);
  this.state = {isModalOpen: false};
}

this.stateの初期値を「isModalOpenがfalse」と決めています。

 

次に2つの関数を定義しています。

 handleClickCity() {
  this.setState({isModalOpen: true});
}

 handleClickClose() {
  this.setState({isModalOpen: false});
}

上は、モーダルを表示させる関数です。

下は、モーダルを非表示にする(初期値に戻す)関数です。

 

render()の中では、まず変数modalを定義します。

次に、this.state.isModalOpenがtrueの時、モーダルを表示させるという処理を行なっています。

  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>
     <button
      className='modal-close-btn'
      onClick={() => this.handleClickClose()}
     >
    とじる
    </button>
   </div>
  </div>
 );
}

 

とじるボタンを押した時は、handleClickClose関数が呼び出されます。

 <button
  className='modal-close-btn'
  onClick={() => this.handleClickClose()}
 >
 とじる
 </button>

 

都市の画像をクリックしたらモーダルが表示される・・・という処理は最後に書かれています。

 return(
  <div className='city-card'>
   <div
    className='city-item'
    onClick={() => {this.handleClickCity()}}
   >
   <p>{this.props.name}</p>
   <img src={this.props.image} />
  </div>
  {modal}
  </div>
);

 

モーダルのCssはこちら

 .modal {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background-color: rgba(0,0,0,0.6);
 }
 .modal-inner {
  position: absolute;
  top: 12%;
  right: 0;
  left: 0;
  width: 480px;
  padding-bottom: 60px;
  margin: auto;
  background-color: rgb(255,255,255);
  border-radius: 8px;
 }
 .modal-header {
  height: 10px;
  width: 100%;
  margin-bottom: 50px;
  border-radius: 8px 8px 0 0;
  background-color: bisque;
  text-align: center;
 }
 .modal-introduction h2{
  color: #5876a3;
  text-align: center;
 }
 .modal-introduction p{
  color: #5876a3;
  width: 384px;
  line-height: 32px;
  text-align: center;
  margin: 36px auto 40px;
 }
 .modal-close-btn {
  font-size: 13px;
  color: #8491a5;
  width: 200px;
  padding: 16px 0;
  border: 0;
  background-color: #f0f4f9;
  cursor: pointer;
  margin-left: 140px;
 }

 

モーダルの基礎はここです。

 .modal {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background-color: rgba(0,0,0,0.6);
 }

 

試しにこの部分以外はコメントアウトしてみると、こうなります。

もうすでにモーダルっぽいです。

f:id:khirok:20200113172028p:plain

 

続いて、こちらを追加すると

 .modal-inner {
  position: absolute;
  top: 12%;
  right: 0;
  left: 0;
  width: 480px;
  padding-bottom: 60px;
  margin: auto;
  background-color: rgb(255,255,255);
  border-radius: 8px;
 }

 

このようにモーダルの中身が表示されました。

f:id:khirok:20200113172305p:plain

 

あとは、中身のパーツを整えて完成です。

 .modal-header {
  height: 10px;
  width: 100%;
  margin-bottom: 50px;
  border-radius: 8px 8px 0 0;
  background-color: bisque;
  text-align: center;
 }
 .modal-introduction h2{
  color: #5876a3;
  text-align: center;
 }
 .modal-introduction p{
  color: #5876a3;
  width: 384px;
  line-height: 32px;
  text-align: center;
  margin: 36px auto 40px;
 }
 .modal-close-btn {
  font-size: 13px;
  color: #8491a5;
  width: 200px;
  padding: 16px 0;
  border: 0;
  background-color: #f0f4f9;
  cursor: pointer;
  margin-left: 140px;
 }

 

f:id:khirok:20200113172503p:plain