React-Leafletでマップを表示

# はじめに

React で地図を表示させ、その上にマーカーを表示させる。[React Leaflet](https://react-leaflet.js.org/docs/start-introduction) を参考に進めた。React の基本的な知識は知っている前提とする。

# React-Leaflet のインストール

以下コマンドで、インストールできる。

```
$ npm install react react-dom leaflet
$ npm install react-leaflet
```

# leaflet コンポーネントの作成

指定座標を中心に地図を表示させ、さらにマーカーを配置するコンポーネントを作成する。任意のディレクトリで SimpleLeaflet.js というファイルを作成し、以下コードを書く。ここでは components/Leaflet ディレクトリの直下に置いた。useState を使うことで指定位置やズームを変更することを見据えて position や zoom を作成しているが、この記事ではとくに用いていない。

```javascript:SimpleLeaflet.js
import React, { useState } from "react";
import "leaflet/dist/leaflet.css";
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";

const SimpleLeaflet = () => {
  const [position, setPosition] = useState({
    lat: 51.505,
    lng: -0.09,
  });
  const [zoom, setZoom] = useState(13);

  return (
    <div>
      <MapContainer center={position} zoom={zoom} style={{ height: "50vh" }}>
        <TileLayer
          attribution='&amp;copy <a href="http://osm.org/copyright";>OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <Marker position={position}>
          <Popup>
            A pretty CSS3 popup. <br /> Easily customizable.
          </Popup>
        </Marker>
      </MapContainer>
    </div>
  );
};

export default SimpleLeaflet;
```

上記コンポーネントを作成後、App.js などに `import SimpleLeaflet from "components/Leaflet/SimpleLeaflet.js";` でコンポーネントを読み込み、出力したい場所で `<SimpleLeaflet />` とすれば以下のように地図を表示することができる。

![Leaflet_without_marker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/77abd0dd-328e-6dfa-db53-08d78b22cc25.png)

`import "leaflet/dist/leaflet.css";` での CSS を読み込みや、`<MapContainer ... style={{ height: "50vh" }}> ` で高さの指定をしない場合は地図が適切に表示されないので注意。

上記ではマーカーがまだ表示されていない。調べたところ、[Marker not appearing for simple example #453](https://github.com/PaulLeCam/react-leaflet/issues/453) を発見。これを参考にコードを追記したところ、マーカーを表示できた。

```javascript:SimpleLeaflet.js
import React, { useState } from "react";
import "leaflet/dist/leaflet.css";
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
// add icons
import Leaflet from "leaflet";
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";

// marker setting
let DefaultIcon = Leaflet.icon({
  iconUrl: icon,
  shadowUrl: iconShadow,
});
Leaflet.Marker.prototype.options.icon = DefaultIcon;

const SimpleLeaflet = () => {
  const [lat, setLat] = useState(51.505);
  const [lng, setLng] = useState(-0.09);
  const [zoom, setZoom] = useState(13);
  const [position, setPosition] = useState({
    lat: 51.505,
    lng: -0.09,
  });

  return (
    <div>
      <MapContainer center={position} zoom={zoom} style={{ height: "50vh" }}>
        <TileLayer
          attribution='&amp;copy <a href="http://osm.org/copyright";>OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <Marker position={position}>
          <Popup>
            A pretty CSS3 popup. <br /> Easily customizable.
          </Popup>
        </Marker>
      </MapContainer>
    </div>
  );
};

export default SimpleLeaflet;
```

クリックすると、ポップアップが表示されることも確認できる。

![Leaflet_with_marker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/054fd58b-34f9-fc67-8a67-54eabd7898fc.png)