React-Leaflet(v2.0-beta)を試す


# はじめに

React-Leafletを試してみます。
最初にリポジトリからソースをダウンロードし、サンプルを動かして大まかを捉えます。
その後、ゼロから作成します。

### 公式サイト
[React-Leaflet · ⚛️ React components for 🍃 Leaflet maps](https://react-leaflet.js.org/en/)
[Installation · React-Leaflet](https://react-leaflet.js.org/docs/en/installation.html)


### v2.0 変更点

v2.0では、React v16.3で導入された新しい[Context API](https://reactjs.org/docs/context.html#api)を活用するようです。


# サンプル

サンプルの実行結果

以下で実行結果を見ることができます
[React-Leaflet v2.0 test](https://sugasaki.github.io/react-leaflet-v2-test/)



# 作成

ゼロから実行します。
npm 等の環境構築は終わっているものとします。

今回のソースは以下に置いてます。

[react-leaflet-v2-test/react-leaflet-v2-test at ad6170fd6ae3ac2bf5a0c526e0f01d56ecc08458 · sugasaki/react-leaflet-v2-test](https://github.com/sugasaki/react-leaflet-v2-test/tree/ad6170fd6ae3ac2bf5a0c526e0f01d56ecc08458/react-leaflet-v2-test)


[react-leaflet-v2-test/react-leaflet-v2-test at master · sugasaki/react-leaflet-v2-test](https://github.com/sugasaki/react-leaflet-v2-test/tree/master/react-leaflet-v2-test)



## create-react-app

create-react-appでreactの雛形プロジェクトを作成します。

```
create-react-app react-leaflet-v2-test
```

## インストール
```
インストール
npm install leaflet react-leaflet@next --save

```


# Examples


[Examples](https://react-leaflet.js.org/docs/en/examples.html)にしたがってやっていきます。

今回は以下の２つをやります。

* A simple Marker with Popup
* Event handling


## A simple Marker with Popup

マーカーを1個表示するだけのシンプルな地図コンポーネントを作成します。

### simpleコンポーネント

src/components/simple.js を追加

```react:simple.js
import React, { Component } from 'react'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet'

export default class SimpleExample extends Component {
    state = {
        lat: 51.505,
        lng: -0.09,
        zoom: 13,
    }

    render() {
        const position = [this.state.lat, this.state.lng]
        return (
            <Map center={position} zoom={this.state.zoom}>
                <TileLayer
                    attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>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>
            </Map>
        )
    }
}
```


### App.js

App.jsを以下のように変更します。

```react:App.js
import Leaflet from 'leaflet'
import React, { Component } from 'react';
import './App.css';
import 'leaflet/dist/leaflet.css';
import SimpleExample from './components/simple'

Leaflet.Icon.Default.imagePath =
  '//cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/'

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

export default App;

```



###  index.css

index.cssを修正

```css:index.css
html, body {
    margin: 10px;
    padding: 0;
    height: 100%;
    width: 100%;
}

#root {
    width: inherit;
    height: inherit;
}


.leaflet-container {
    width: 600px;
    height: 300px;
    margin: 10px;
}

```


### 結果

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/2c1cf20f-5252-f5f2-5018-509f9f0d18b4.png)



## Event handling

クリックを検知してイベント発火、イベントでは現在地の取得を行います。


### eventsコンポーネント

src/components/events.js を追加

```react:events.js
import React, { createRef, Component } from 'react'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet'

export default class EventsExample extends Component {
    state = {
        hasLocation: false,
        latlng: {
            lat: 51.505,
            lng: -0.09,
        },
    }

    mapRef = createRef()

    handleClick = () => {
        this.mapRef.current.leafletElement.locate()
    }

    handleLocationFound = e => {
        this.setState({
            hasLocation: true,
            latlng: e.latlng,
        })
    }

    render() {
        const marker = this.state.hasLocation ? (
            <Marker position={this.state.latlng}>
                <Popup>
                    <span>You are here</span>
                </Popup>
            </Marker>
        ) : null

        return (
            <Map
                center={this.state.latlng}
                length={4}
                onClick={this.handleClick}
                onLocationfound={this.handleLocationFound}
                ref={this.mapRef}
                zoom={13}>
                <TileLayer
                    attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                {marker}
            </Map>
        )
    }
}
```


### App.js

eventsの参照を追加します。
`import EventsExample from './components/events'`

また、renderに`<EventsExample />`を追加します。
App.jsを以下のように変更します。


```react:App.js
import Leaflet from 'leaflet'
import React, { Component } from 'react';
import './App.css';
import 'leaflet/dist/leaflet.css';
import SimpleExample from './components/simple'
import EventsExample from './components/events'

Leaflet.Icon.Default.imagePath =
  '//cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/'


class App extends Component {
  render() {
    return (
      <div>
        SimpleExample
        <SimpleExample />

        EventsExample
        <EventsExample />
      </div>
    );
  }
}

export default App;
```



### 結果

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/ba0a9f8f-5e4d-1160-65c8-2155bb09035f.png)