ReactでGoogle mapをお届けする

# はじめに

ReactでMapを使用し以下要件を満たす必要があった

```
・ マップスタイルの変更
・ ピンスタイルの変更
・ ピン間に線を描画する
・ ピンをクリックすると吹き出しが表示される
```

要件を満たすためにReactで使用可能なMapをレンダリングできるライブラリをざっと調査した

# ライブラリ

| ライブラリ	| ピン変更 | バルーン機能 | ルーティング | 備考 |
| ---- | ---- | ---- | ---- | ---- |
| [google-maps-react](https://www.npmjs.com/package/google-maps-react)| Markerコンポーネントを提供している|infoWindowで変更可能|polylineで設定可能| weekly download 24,085|
| [google-map-react](https://www.npmjs.com/package/google-map-react)| 子コンポ-ネント内に画像やスタイルを適用したコンポーネントで対応|子コンポーネントで吹き出しコンポーネントを配置しonChildClickで表示する|onGoogleApiLoaded時に描画可能|weekly download 69,369 |
| [react-google-maps](https://www.npmjs.com/package/react-google-map)| componentのcoordinates内で変更可能|infoWindowをカスタム| onLoaded時に描画可能| ・weekly download 2,414<br>UI componentを豊富に提供 |
| [2gis-maps-react](https://www.npmjs.com/package/2gis-maps-react)| 細かいアイコンの設定が可能|popuupで設定可能|polylineで線を引ける| ・no longer supported<br>・weekly download 15|
| [react-map-gl](https://www.npmjs.com/package/react-map-gl)| markerで設定可能|popuupで設定可能|overlay機能を仕様しcanvasに線を引ける| ・mapboxを使用可能<br>・weekly download 34,397|
今回は単純にコミュニティがアクティブかどうか、公式サンプルが豊富かという視点で[google-map-react](https://www.npmjs.com/package/google-map-react)を使用することにした

また、マップスタイルの変更として[snazzymaps](https://snazzymaps.com/)が豊富なサンプルを提供しているので今回使用することにした

# 実装
google-map-reactでピンを一個だけマップ上に表示したい場合はとても簡単に実装できる

```react
import * as React from 'react'
import styled from 'styled-components'
import logo from './logo.svg'
import GoogleMapReact from 'google-map-react'

const App = () => (
  <Wrapper>
    <Header>
      <Logo src={logo} />
      <H1>Welcome to React</H1>
    </Header>
    <GoogleMapWrapper>
    <GoogleMapReact
      bootstrapURLKeys={{
        key: {'ここにgoogle map apiのkeyをドウゾ'}
      }}
      defaultCenter={{
        lat: 43.0582954,
        lng: 141.3466919
      }}
      defaultZoom={15}
    >
      <Pin
        lat={43.0582954}
        lng={141.3466919}
      >
      おおおんどおり
      </Pin>
    </GoogleMapReact>
    </GoogleMapWrapper>
  </Wrapper>
)

const Wrapper = styled.div`
  text-align: center;
`
const Header = styled.header`
  background-color: ${Color.Primary};
  height: 150px;
  padding: 20px;
  color: white;
`
const Logo = styled.img`
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
  @keyframes App-logo-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`
const H1 = styled.h1`
  font-size: 1.5em;
`
const Pin = styled.div<{
  lat: number,
  lng: number
}>`
`

const GoogleMapWrapper = styled.div`
  height: 100vh;
  width: 100%;
`

export default App
```
これを適用すると大通公園に"おおおんどおり"と表示されてるはずだ
サンプルを参考にするだけでとても簡単にピンを配置できる

## マップスタイル変更
Googleマップのデザインを以下のように変更したいケースがあると思う
<img src="https://snazzy-maps-cdn.azureedge.net/assets/38-shades-of-grey.png?v=20170626083726">
<img src="https://snazzy-maps-cdn.azureedge.net/assets/253587-fnjkdv.png?v=20190216061526">
実は[snazzymap](https://snazzymaps.com/)というサイトを使えば簡単に実装できる

```react
import * as React from 'react'
import styled from 'styled-components'
import { Color } from './brand'
import logo from './logo.svg'
import GoogleMapReact, { MapOptions, Maps } from 'google-map-react'

const App = () => {
  const createMapOptions = (maps: Maps): MapOptions => {
    return {
      mapTypeControlOptions: {
        position: maps.ControlPosition.TOP_RIGHT,
      },
      mapTypeControl: false,
      zoomControl: false,
      scaleControl: false,
      streetViewControl: false,
      fullscreenControl: false,
      styles: [
        {
          featureType: 'water',
          elementType: 'geometry',
          stylers: [
            {
              color: '#e9e9e9',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'landscape',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 29,
            },
            {
              weight: 0.2,
            },
          ],
        },
        {
          featureType: 'road.arterial',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 18,
            },
          ],
        },
        {
          featureType: 'road.local',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          featureType: 'poi',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          featureType: 'poi.park',
          elementType: 'geometry',
          stylers: [
            {
              color: '#dedede',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          elementType: 'labels.text.stroke',
          stylers: [
            {
              visibility: 'on',
            },
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          elementType: 'labels.text.fill',
          stylers: [
            {
              saturation: 36,
            },
            {
              color: '#333333',
            },
            {
              lightness: 40,
            },
          ],
        },
        {
          elementType: 'labels.icon',
          stylers: [
            {
              visibility: 'off',
            },
          ],
        },
        {
          featureType: 'transit',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f2f2f2',
            },
            {
              lightness: 19,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 17,
            },
            {
              weight: 1.2,
            },
          ],
        },
      ],
    }
  }
  return (
    <Wrapper>
      <Header>
        <Logo src={logo} />
        <H1>Welcome to React</H1>
      </Header>
      <GoogleMapWrapper>
      <GoogleMapReact
        bootstrapURLKeys={{
          key: ''
        }}
        defaultCenter={{
          lat: 43.0582954,
          lng: 141.3466919
        }}
        defaultZoom={15}
        options={createMapOptions}
      >
        <Pin
          lat={43.0582954}
          lng={141.3466919}
        >
        おおおんどおり
        </Pin>
      </GoogleMapReact>
      </GoogleMapWrapper>
    </Wrapper>
  )
}

const Wrapper = styled.div`
  text-align: center;
`
const Header = styled.header`
  background-color: ${Color.Primary};
  height: 150px;
  padding: 20px;
  color: white;
`
const Logo = styled.img`
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
  @keyframes App-logo-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`
const H1 = styled.h1`
  font-size: 1.5em;
`
const Pin = styled.div<{
  lat: number,
  lng: number
}>`
`

const GoogleMapWrapper = styled.div`
  height: 100vh;
  width: 100%;
`

export default App
```
createMapOptionsのfullscreenControl optionの下にstyles optionがある
このstyles optionにsnazzymapで取得したソースコードをコピペするだけで実装できる

ちなみに今回は[Subtle Grayscale](https://snazzymaps.com/style/15/subtle-grayscale)を適用した

## ピンスタイルの変更
前述通りピンを１個だけ描画したい場合はとても簡単にできるが複数ピンのスタイルを変更し描画したい場合はどうすればいいのかともしかしたらなるかもしれない
これも簡単に実装できる

複数ピンの描画位置に関しては、GoogleMapReactの１階層子コンポーネントでlatやlngを元に相対位置をよしなに算出してくれるので子コンポーネントにスタイルを適用するだけで実装ができる

```react
import * as React from 'react'
import styled from 'styled-components'
import { Color } from './brand'
import logo from './logo.svg'
import GoogleMapReact, { MapOptions, Maps } from 'google-map-react'

const App = () => {
  const pins: {
    lat: number,
    lng: number,
    name: string
  }[] = [
    {
      lat: 43.0543412,
      lng: 141.355018,
      name: 'お姉さんレーベル'
    },
    {
      lat: 43.0543451,
      lng: 141.3528293,
      name: '姉キャバ ジャックローズ'
    }
  ]
  const createMapOptions = (maps: Maps): MapOptions => {
    return {
      mapTypeControlOptions: {
        position: maps.ControlPosition.TOP_RIGHT,
      },
      mapTypeControl: false,
      zoomControl: false,
      scaleControl: false,
      streetViewControl: false,
      fullscreenControl: false,
      styles: [
        {
          featureType: 'water',
          elementType: 'geometry',
          stylers: [
            {
              color: '#e9e9e9',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'landscape',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 29,
            },
            {
              weight: 0.2,
            },
          ],
        },
        {
          featureType: 'road.arterial',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 18,
            },
          ],
        },
        {
          featureType: 'road.local',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          featureType: 'poi',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          featureType: 'poi.park',
          elementType: 'geometry',
          stylers: [
            {
              color: '#dedede',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          elementType: 'labels.text.stroke',
          stylers: [
            {
              visibility: 'on',
            },
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          elementType: 'labels.text.fill',
          stylers: [
            {
              saturation: 36,
            },
            {
              color: '#333333',
            },
            {
              lightness: 40,
            },
          ],
        },
        {
          elementType: 'labels.icon',
          stylers: [
            {
              visibility: 'off',
            },
          ],
        },
        {
          featureType: 'transit',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f2f2f2',
            },
            {
              lightness: 19,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 17,
            },
            {
              weight: 1.2,
            },
          ],
        },
      ],
    }
  }
  return (
    <Wrapper>
      <Header>
        <Logo src={logo} />
        <H1>Welcome to React</H1>
      </Header>
      <GoogleMapWrapper>
      <GoogleMapReact
        bootstrapURLKeys={{
          key: ''
        }}
        defaultCenter={{
          lat: 43.0543451,
          lng: 141.3528293
        }}
        defaultZoom={15}
        options={createMapOptions}
      >
      {
        pins.map((pin: {
          lat: number,
          lng: number,
          name: string
        }) => (
          <Pin
            lat={pin.lat}
            lng={pin.lng}
          >
          {pin.name}
          </Pin>
        ))
      }
      </GoogleMapReact>
      </GoogleMapWrapper>
    </Wrapper>
  )
}

const Wrapper = styled.div`
  text-align: center;
`
const Header = styled.header`
  background-color: ${Color.Primary};
  height: 150px;
  padding: 20px;
  color: white;
`
const Logo = styled.img`
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
  @keyframes App-logo-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`
const H1 = styled.h1`
  font-size: 1.5em;
`
const Pin = styled.div<{
  lat: number,
  lng: number
}>`
`

const GoogleMapWrapper = styled.div`
  height: 100vh;
  width: 100%;
`

export default App

```
お姉さんレーベルと姉キャバ ジャックローズが表示されてることが確認できると思う
あとは、Pinコンポーネントのstyleを変更すればデザインは簡単に変更可能だ

## ピン間に線を描画する
GoogleMapReactではGoogle map apiのloaded時に上乗せ描画できるapiを提供している
例えば線を描画するpolylineがある
今回はpolylineを使用しでピン間に線を引く

```react
import * as React from 'react'
import styled from 'styled-components'
import { Color } from './brand'
import logo from './logo.svg'
import GoogleMapReact, { MapOptions, Maps } from 'google-map-react'
interface PinProps {
  lat: number,
  lng: number,
  name: string
}
const App = () => {
  const pins: PinProps[] = [
    {
      lat: 43.0543412,
      lng: 141.355018,
      name: 'お姉さんレーベル'
    },
    {
      lat: 43.0543451,
      lng: 141.3528293,
      name: '姉キャバ ジャックローズ'
    }
  ]
  const apiLoaded = (map: any, maps: any, pins: any) => {
    const path = new maps.Polyline({
      path: pins.map((p: PinProps) => ({
        lat: p.lat,
        lng: p.lng
      })),
      geodesic: true,
      strokeColor: '#356859',
      strokeOpacity: 1,
      strokeWeight: 3,
    })

    path.setMap(map)
  }
  const createMapOptions = (maps: Maps): MapOptions => {
    return {
      mapTypeControlOptions: {
        position: maps.ControlPosition.TOP_RIGHT,
      },
      mapTypeControl: false,
      zoomControl: false,
      scaleControl: false,
      streetViewControl: false,
      fullscreenControl: false,
      styles: [
        {
          featureType: 'water',
          elementType: 'geometry',
          stylers: [
            {
              color: '#e9e9e9',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'landscape',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 29,
            },
            {
              weight: 0.2,
            },
          ],
        },
        {
          featureType: 'road.arterial',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 18,
            },
          ],
        },
        {
          featureType: 'road.local',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          featureType: 'poi',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          featureType: 'poi.park',
          elementType: 'geometry',
          stylers: [
            {
              color: '#dedede',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          elementType: 'labels.text.stroke',
          stylers: [
            {
              visibility: 'on',
            },
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          elementType: 'labels.text.fill',
          stylers: [
            {
              saturation: 36,
            },
            {
              color: '#333333',
            },
            {
              lightness: 40,
            },
          ],
        },
        {
          elementType: 'labels.icon',
          stylers: [
            {
              visibility: 'off',
            },
          ],
        },
        {
          featureType: 'transit',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f2f2f2',
            },
            {
              lightness: 19,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 17,
            },
            {
              weight: 1.2,
            },
          ],
        },
      ],
    }
  }
  return (
    <Wrapper>
      <Header>
        <Logo src={logo} />
        <H1>Welcome to React</H1>
      </Header>
      <GoogleMapWrapper>
      <GoogleMapReact
        bootstrapURLKeys={{
          key: ''
        }}
        defaultCenter={{
          lat: 43.0543451,
          lng: 141.3528293
        }}
        defaultZoom={15}
        options={createMapOptions}
        onGoogleApiLoaded={({ map, maps }) => apiLoaded(map, maps, pins)}
      >
      {
        pins.map((pin: {
          lat: number,
          lng: number,
          name: string
        }) => (
          <Pin
            lat={pin.lat}
            lng={pin.lng}
          >
          {pin.name}
          </Pin>
        ))
      }
      </GoogleMapReact>
      </GoogleMapWrapper>
    </Wrapper>
  )
}

const Wrapper = styled.div`
  text-align: center;
`
const Header = styled.header`
  background-color: ${Color.Primary};
  height: 150px;
  padding: 20px;
  color: white;
`
const Logo = styled.img`
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
  @keyframes App-logo-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`
const H1 = styled.h1`
  font-size: 1.5em;
`
const Pin = styled.div<{
  lat: number,
  lng: number
}>`
`

const GoogleMapWrapper = styled.div`
  height: 100vh;
  width: 100%;
`

export default App

```
お姉さんレーベルと姉キャバ ジャックローズの間に緑色の線が引かれていることが確認できるだろう

## ピンをクリックすると吹き出しが表示される
GoogleMapReactは子コンポーネントのクリック時にイベント取得するonChildClickというapiを提供している
onChildClickはイベント発生時に該当するコンポーネントのkeyと子コンポーネント自体の情報(childProps)を返す

基本吹き出しを表示する際はクリックイベントのkeyとmapのindexが同じなら表示するで実装できるので、基本childPropsは使用しなくていいだろう

```react
import * as React from 'react'
import styled from 'styled-components'
import { useState } from 'react'
import { Color } from './brand'
import logo from './logo.svg'
import GoogleMapReact, { MapOptions, Maps } from 'google-map-react'
interface PinProps {
  lat: number,
  lng: number,
  name: string
}
const App = () => {
  const [currentKey, setCurrentKey] = useState(-1)
  const pins: PinProps[] = [
    {
      lat: 43.0543412,
      lng: 141.355018,
      name: 'お姉さんレーベル'
    },
    {
      lat: 43.0543451,
      lng: 141.3528293,
      name: '姉キャバ ジャックローズ'
    }
  ]
  const apiLoaded = (map: any, maps: any, pins: any) => {
    const path = new maps.Polyline({
      path: pins.map((p: PinProps) => ({
        lat: p.lat,
        lng: p.lng
      })),
      geodesic: true,
      strokeColor: '#356859',
      strokeOpacity: 1,
      strokeWeight: 3,
    })

    path.setMap(map)
  }
  const changeBalloon = (key: string) => {
    const keyNumber = Number(key)
    if (currentKey === keyNumber) {
      setCurrentKey(-1)
    } else {
      setCurrentKey(keyNumber)
    }
  }
  const createMapOptions = (maps: Maps): MapOptions => {
    return {
      mapTypeControlOptions: {
        position: maps.ControlPosition.TOP_RIGHT,
      },
      mapTypeControl: false,
      zoomControl: false,
      scaleControl: false,
      streetViewControl: false,
      fullscreenControl: false,
      styles: [
        {
          featureType: 'water',
          elementType: 'geometry',
          stylers: [
            {
              color: '#e9e9e9',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'landscape',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 17,
            },
          ],
        },
        {
          featureType: 'road.highway',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 29,
            },
            {
              weight: 0.2,
            },
          ],
        },
        {
          featureType: 'road.arterial',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 18,
            },
          ],
        },
        {
          featureType: 'road.local',
          elementType: 'geometry',
          stylers: [
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          featureType: 'poi',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f5f5f5',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          featureType: 'poi.park',
          elementType: 'geometry',
          stylers: [
            {
              color: '#dedede',
            },
            {
              lightness: 21,
            },
          ],
        },
        {
          elementType: 'labels.text.stroke',
          stylers: [
            {
              visibility: 'on',
            },
            {
              color: '#ffffff',
            },
            {
              lightness: 16,
            },
          ],
        },
        {
          elementType: 'labels.text.fill',
          stylers: [
            {
              saturation: 36,
            },
            {
              color: '#333333',
            },
            {
              lightness: 40,
            },
          ],
        },
        {
          elementType: 'labels.icon',
          stylers: [
            {
              visibility: 'off',
            },
          ],
        },
        {
          featureType: 'transit',
          elementType: 'geometry',
          stylers: [
            {
              color: '#f2f2f2',
            },
            {
              lightness: 19,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.fill',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 20,
            },
          ],
        },
        {
          featureType: 'administrative',
          elementType: 'geometry.stroke',
          stylers: [
            {
              color: '#fefefe',
            },
            {
              lightness: 17,
            },
            {
              weight: 1.2,
            },
          ],
        },
      ],
    }
  }
  return (
    <Wrapper>
      <Header>
        <Logo src={logo} />
        <H1>Welcome to React</H1>
      </Header>
      <GoogleMapWrapper>
        <GoogleMapReact
          bootstrapURLKeys={{
            key: ''
          }}
          defaultCenter={{
            lat: 43.0543451,
            lng: 141.3528293
          }}
          defaultZoom={15}
          options={createMapOptions}
          onGoogleApiLoaded={({ map, maps }) => apiLoaded(map, maps, pins)}
          onChildClick={(key: string) => changeBalloon(key)}
        >
        {
          pins.map((
            pin: {
              lat: number,
              lng: number,
              name: string
            },
            index: number) => (
            <Pin
              lat={pin.lat}
              lng={pin.lng}
            >
            {pin.name}
            {
              index === currentKey &&
              'こんにちは'
            }
            </Pin>
          ))
        }
        </GoogleMapReact>
      </GoogleMapWrapper>
    </Wrapper>
  )
}

const Wrapper = styled.div`
  text-align: center;
`
const Header = styled.header`
  background-color: ${Color.Primary};
  height: 150px;
  padding: 20px;
  color: white;
`
const Logo = styled.img`
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
  @keyframes App-logo-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`
const H1 = styled.h1`
  font-size: 1.5em;
`
const Pin = styled.div<{
  lat: number,
  lng: number
}>`
`

const GoogleMapWrapper = styled.div`
  height: 100vh;
  width: 100%;
`

export default App

```
それぞれの子コンポーネントをクリックすると"こんにちは"が表示されるだろう
onGoogleApiLoadedのmapsからgoogle apiのdraw機能を扱うことができる
[参照](https://developers.google.com/maps/documentation/javascript/overlays)

useStateがよくわからねえという方は自分で勉強してください

#まとめ
今回使用したライブラリの使用事例の記事がなかなか見つからなかったので、今回記事にし公開することにした
これからReactでgoogle mapの使用を検討している方に少しでも参考になれば幸いだ

今回作成したサンプルは[こちら](https://github.com/miyabiya/react-google-map)