Essential setup steps to use React-Leaflet

Page content

Using Leaflet in a React project, especially a create-react-app project can be tricky. In a React app, the UI are composed by components. Each component encapsulate some logic and states to itself. This is different from traditional ways of writing HTML + CSS + JavaScript. This is why many traditional JS libraries like Bootstrap and Semantic-UI have React-specific counterparts (React-Bootstrap and Semantic-UI React) to allow using them in the React way. Leaflet is no different. Although there is no official React-bindings for Leaflet, React-Leaflet is one popular choice out there. However, the React-Leaflet documentation is not very clear on how to properly setup in order to correctly show the map, at least not very clear to me.

Here is a quick setup for React-Leaflet in a create-react-app project:

First step is to install Leaflet and React-Leaflet from commandline interface in project folder:

npm install leaflet react-leaflet

Import Leaflet CSS

Traditionally, you need to include Leaflet CSS in the HTML <head> tag like this:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
  integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
  crossorigin=""/>

And include Leaflet JS file like this:

<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
   integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
   crossorigin=""></script>

You can still do this in the public/index.html file in the project. However, since we already installed Leaflet via NPM, the package will be bundled into the final build, which means that we can directly use them from the local Leaflet package stored in node_modules/ to avoid requesting them again.

Suppose the file you want to write the map component is src/map.jsx, you can import the Leaflet CSS file directly by putting import "leaflet/dist/leaflet.css" at the top of src/map.jsx. Then you can write your map component in the file as usual. You don’t need to worry about Leaflet JS file as the webpack will bundle the JS file in the final build automatically. One advantage of this approach is that once you update Leaflet version via NPM, your code will use the new version automatically.

Solve the “Failed to compile : ./node_modules/@react-leaflet/core/esm/path.js 10:41 Module parse failed: Unexpected token (10:41)” error

If you are using create-react-app and Leaflet, you might encounter this issue when you try to do npm start. At least at the time of this article, with my create-react-app version 4.0.3, the issue is still not resolved. There are some discussions about this issue on Stackoverflow, and the solutions reduce to replace the browser list in package.json to the below, as the original target browsers might be too aggressive.

// package.json
{
  ...
  "browserslist": [
    ">0.2%",
    "not dead",
    "not op_mini all"
  ]
}

One last step

If you read carefully the React-Leaflet doc and Leaflet doc, you may endup at last step, but you may notice your map still does not show up on your page. This is because leaflet by default does not set container width and height. Traditionally, Leaflet ask you to write a map container div like this:

<div id="#map" style="width:500px;height:300px;"></div>

and then put map in this div in JS like this:

var mymap = L.map('map')

Naturally, you may want to put a div around the <MapContainer /> component from React-Leaflet, and set the height and width of it, but nope, it does not work. The reason is the <MapContainer /> already contains a such div and you need to set height and width of that contained div. You can do it by selecting the leaflet-container class in CSS, which is by default included in the container div. Or, you can set an id or your own class for the <MapContainer /> component and reference it in the CSS. Here is an example using default class leaflet-container.

.leaflet-container {
  width: 100vw;
  height: 100vh;
}

Voila, you should then see the map.

Sample Code

src/map.jsx:

import React from 'react'
import { MapContainer, TileLayer } from "react-leaflet";
import 'leaflet/dist/leaflet.css'

export default function Map() {
  return (
    <MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={false} id="map">
      <TileLayer
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
    </MapContainer>
  )
}

src/App.css:

.leaflet-container {
  width: 100vw;
  height: 100vh;
}
/* or */
#map {
  width: 100vw;
  height: 100vh;
}