React + Google Maps APIでモーダル上にマップを表示する

Qiita初投稿です。最近ReactでGoogle Maps APIを扱うことが多いので自分用のTipsにする目的も兼ねて投稿してみました。

#最初の手順
1. `$ create-react-app 'プロジェクト名'` で雛形を作成
2. `npm i --save react-modal` コマンドでModalをコンポーネントとして扱えるようパッケージをinstall
3. [ここ](https://developers.google.com/maps/documentation/javascript/?hl=ja)からMaps用APIキー取得
    - 参考 : [Google Maps APIを使って、サイト上に地図を表示するまでの流れ ｜ Tips Note by TAM](https://www.tam-tam.co.jp/tipsnote/javascript/post12851.html)
4. public/index.html 内に`<script>`タグでAPIキーを埋め込み
    - 例: `<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=取得したAPIキー"></script>`

#コンポーネントの構造
以下の通り。

- App (親コンポーネント)
    - Modal (子コンポーネント)
        - Map　（孫コンポーネント）　

#ソースコード
###親コンポーネント(App) + 子コンポーネント(Modal)
```JavaScript:App.js
import React, { Component } from 'react'
import './App.css'
import ReactDOM from 'react-dom'
import Modal from 'react-modal'

export default class App extends Component {
  constructor (props) {
    super(props)
    this.state = {
      showModal: false,
    }
    this.openModal = this.openModal.bind(this)
    this.closeModal = this.closeModal.bind(this)
  }

  openModal(){
    this.setState({showModal: true})
  }

  closeModal(){
    this.setState({showModal: false})
  }

  render(){
    const custom = {
      overlay : {
        background: 'rgba(0,0,0, .4)'
      },
      content : {
        top                   : '50%',
        left                  : '50%',
        right                 : 'auto',
        bottom                : 'auto',
        marginRight           : '-50%',
        transform             : 'translate(-50%, -50%)',
        width                 : '72%',
        height                : '80%'
      }
    }
    return (
      <div className="AppComponent">
        <input type="submit" className="button--submit" onClick={this.openModal} value="Open Map"/>
        <Modal isOpen={this.state.showModal} shouldCloseOnOverlayClick={true}
               onRequestClose={this.closeModal} style={custom} >
          <Map />
        </Modal>
      </div>
    )
  }
}
```
Modalコンポーネントはreact-modalからインポートしてそのまま使うので、スタイルなどもまとめて親コンポーネントのクラス内に記述。`isOpen`がTrueになった時にModalが表示されます。
今回は親コンポーネント上にボタンを置いて、それがクリックされることによってshowModalの状態をトグルして表示させています。
`shouldCloseOnOverlayClick`がTrueならオーバーレイ部分をクリックするとModalが閉じる。
`style`でModalのスタイルを直接render()内に記述することで指定できるのですが、他に良い方法がありそう・・・
###孫コンポーネント(Map)
```JavaScript:App.js
export class Map extends Component{
  constructor(props){
    super(props)

    this.state=({
      map: null,
    })
  }

  componentDidMount () {
    const map = new window.google.maps.Map(
      ReactDOM.findDOMNode(this.refs["map"]),
      // document.getElementById('modalMap'),
      {
        center: new window.google.maps.LatLng(35.466642, 139.622485), //横浜駅
        zoom: 17,
        mapTypeId: 'roadmap'
      }
    );
    this.setState({"map":map})
    console.log('map is open')
  }

  render(){
    return(
      <div className="modal--map">
        {/*<div ref="modalMap" className="modalMap"></div>*/}　//document.getElementByIdを使う場合
        <div ref="map" id="modalMap"/>
      </div>
    )
  }

}
```
`<div className="modal--map">`がrenderされてDOMツリーに追加された後にMapオブジェクトを`componentDidMount()`で呼び出す仕組み。render内にmapのプロパティをベタ書きすると多分エラーになります、たしか。今回は`ReactDOM.findDOMNode`でref属性を持ったdivにMapを描画していますが、`document.getElementById`を使う書き方も可能です。

#まとめ
Mapをコンポーネントとして実装するなら[react-google-maps](https://github.com/tomchentw/react-google-maps)を素直に使うほうが間違いなく近道ではあるのですが、単にちょっと表示させたいなら上記の方法で済ますこともいいのではないでしょうか。
ここから、Map上のマーカーをさらに子コンポーネントとして追加したり、Modalの中にMapと並列となるコンポーネントを追加して何かウェブアプリを構築していくのもいいかなーと考えています。

#参考リンク
[Reactでcontextを利用してGoogleMapAPIを叩く(Map,Marker)]
(https://qiita.com/sh4869/items/fcbcc6dee76d42572566)

[Google Maps JavaScript API 概要]
(https://developers.google.com/maps/documentation/javascript/?hl=ja)

[react-modal]
(https://github.com/reactjs/react-modal)