ReactHooksでGoogleMapAPIを扱う

#何を作るか

googleMapAPIを使ってgooglemapっぽいのを作りましたので、そのまとめです。
React使いたいな〜って単純な理由でReactで作りましたが、差分更新が簡単にできたので嬉しかったです:open_hands:

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325594/c076a6cb-3fe1-97b7-f11e-bc65c1850d3d.gif)

長くなってしまうので、とりあえず
- map表示
- 現在地表示
- 吹き出し表示
まで！

#環境構築
create-react-appで作っていきます。

```
create-react-app map
cd map
yarn start
```

TSで作るなら

```
create-react-app map --typescript
cd map
yarn start
```

使用するライブラリは`google-map-react`です。
googlemapをReactで扱うにはいろんなライブラリがありますが、単純に参考記事の多さで選びました。
[google-map-react 公式](https://github.com/google-map-react/google-map-react/blob/master/API.md#ondragend-map--void)

```
yarn add -D google-map-react
// Typescript使うなら↓
yarn add -D @types/google-map-react
```

あとはAPIキーを取得しなきゃですが、そこは割愛…

# Map表示

直接でも良いですがApp.jsはMapのレンダリングに使います。

```App.js
import React, { Component } from "react";
import Maps from "./Maps";

class App extends Component {
  render() {
    return (
      <div>
        <Maps />
      </div>
    );
  }
}

export default App;
```

```Maps.js
import React, { useState, useEffect } from "react";
import GoogleMapReact from "google-map-react";

//APIKEYは""としていれば開発者モードで使えます
const APIKEY = "";

const Maps = () => {
  const [center, setCenter] = useState({ lat: "", lng: "" });
  const [zoom, setZoom] = useState(13);
  
  return (
    //高さ指定してあげないとMap出ません！
    <div style={{ height: "100vh", width: "100%" }}>
　　　　//google-map-reactからimport!
　　　　//bootstrapURLKeys,center,zoom値があれば表示されます
      <GoogleMapReact
        bootstrapURLKeys={{ key: APIKEY }}
        center={center}
        defaultZoom={zoom}
      >
      </GoogleMapReact>
    </div>
  );
};

export default Maps;

```
#現在地表示
カスタムマーカーを作るのはgoogle-map-reactを使えば簡単にできました！
GoogleMapReactに子コンポーネントとして書き込み、緯度経度を持たせてあげるだけです:eyes:

```Maps.js
<GoogleMapReact
  bootstrapURLKeys={{ key: APIKEY }}
  center={center}
  defaultZoom={zoom}
 >  
    <Marker
     lat={XXXXXXXXX}
     lng={XXXXXXXXX}
    />       
</GoogleMapReact>
```

これをgeolocationを使って現在地に反映させます。


```Maps.js

const Maps = () => {

　//centerなどの値もState管理に
  const [center, setCenter] = useState({ lat: "", lng: "" });
  const [zoom, setZoom] = useState(13);
  const [currentPosition, setCurrentPosition] = useState();

  // 初期表示地点
  const success = data => {
    const currentPosition = {
      lat: data.coords.latitude,
      lng: data.coords.longitude
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };

  //geolocation使えない場合の値を返す
  const error = data => {
    const currentPosition = {
      lat: 34.673542,
      lng: 135.433338
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };
　//初期読み込み時のみgeolocationを動かす
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(success, error);
  }, []);

  return (
    <div style={{ height: "100vh", width: "100%" }}>
      <GoogleMapReact
        bootstrapURLKeys={{ key: APIKEY }}
        center={center}
        defaultZoom={zoom}
      >
        {currentPosition ? (
          <Marker
            lat={currentPosition.lat}
            lng={currentPosition.lng}
          />
        ) : null}
      </GoogleMapReact>
    </div>
  );
};

export default Maps;
```


#吹き出し表示
Openかどうかをstate管理し、trueであれば表示します

```Maps.js
const Maps = () => {
  
  const [isOpen, setIsOpen] = useState(false);
  const changeState = () => {
    setIsOpen(!isOpen);
  };

  return (
　　　　　：
        {isOpen ? (
          <Baloon lat={currentPosition.lat} lng={currentPosition.lng} />
        ) : null}
      </GoogleMapReact>
    </div>
  );
};

export default Maps;

```

```Maps.js

const Maps = () => {

  const [center, setCenter] = useState({ lat: "", lng: "" });
  const [zoom, setZoom] = useState(13);
  const [currentPosition, setCurrentPosition] = useState();
  const [isOpen, setIsOpen] = useState(false);

  // 初期表示地点
  const success = data => {
    const currentPosition = {
      lat: data.coords.latitude,
      lng: data.coords.longitude
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };

  const error = data => {
    const currentPosition = {
      lat: 34.673542,
      lng: 135.433338
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(success, error);
  }, []);

  const changeState = () => {
    setIsOpen(!isOpen);
  };

  return (
    <div style={{ height: "100vh", width: "100%" }}>
      <GoogleMapReact
        bootstrapURLKeys={{ key: APIKEY }}
        center={center}
        defaultZoom={zoom}
      >
        {currentPosition ? (
          <Marker
            lat={currentPosition.lat}
            lng={currentPosition.lng}
            text="My Marker"
            color="blue"
            changeState={changeState}
          />
        ) : null}
        {isOpen ? (
          <Baloon lat={currentPosition.lat} lng={currentPosition.lng} />
        ) : null}
      </GoogleMapReact>
    </div>
  );
};

export default Maps;

```


なので全体はこんな感じ↓

```Maps.js
import React, { useState, useEffect } from "react";
import GoogleMapReact from "google-map-react";
import "../styles.css";
const APIKEY = "";

const Maps = () => {
  const [center, setCenter] = useState({ lat: 34.665442, lng: 135.432338 });
  const [zoom, setZoom] = useState(13);
  const [currentPosition, setCurrentPosition] = useState();
  const [isOpen, setIsOpen] = useState(false);

  // 初期表示地点
  const success = data => {
    const currentPosition = {
      lat: data.coords.latitude,
      lng: data.coords.longitude
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };

  const error = data => {
    const currentPosition = {
      lat: 34.673542,
      lng: 135.433338
    };
    setCurrentPosition(currentPosition);
    setCenter(currentPosition);
  };
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(success, error);
  }, []);

  const changeState = () => {
    setIsOpen(!isOpen);
  };

  return (
    <div style={{ height: "100vh", width: "100%" }}>
      <GoogleMapReact
        bootstrapURLKeys={{ key: APIKEY }}
        center={center}
        defaultZoom={zoom}
      >
        {currentPosition ? (
          <Marker
            lat={currentPosition.lat}
            lng={currentPosition.lng}
            text="My Marker"
            color="blue"
            changeState={changeState}
          />
        ) : null}
        {isOpen ? (
          <Baloon lat={currentPosition.lat} lng={currentPosition.lng} />
        ) : null}
      </GoogleMapReact>
    </div>
  );
};

export default Maps;

```

Markerとかは切り分けて普通に作ればOKです！
↓こんな感じに
https://codesandbox.io/embed/google-maps-react-9slxw?fontsize=14&hidenavigation=1&theme=dark

とりあえず基本のところまで書いてみました。
詰まったところいっぱいあるのでかいつまんで残していきます:writing_hand:

# 参考記事
公式
https://github.com/google-map-react/google-map-react/blob/master/API.md#ondragend-map--void

基本表示まで
https://levelup.gitconnected.com/reactjs-google-maps-with-custom-marker-ece0c7d184c4

https://levelup.gitconnected.com/google-map-react-beginners-guide-85bb1a94b04a

geolocationで現在地を初期表示に
https://medium.com/@allynak/how-to-use-google-map-api-in-react-app-edb59f64ac9d

高さ固定
https://github.com/tomchentw/react-google-maps/issues/323

googlemapAPIに関するヒントいろいろ
https://www.granfairs.com/blog/staff/google-maps-api-03