Skip to content

Getting Started with React Leaflet

Free

Starter

Standard

Professional

If you need to visualize geospatial data in a web application, using React can greatly simplify your life as a developer. The benefits are especially obvious if you're working with large amounts of data or need to respond to filters and other user or backend actions.

This tutorial will show you how to use Leaflet, a battle-tested mapping library, with React to make an interactive map of every video arcade in Japan.

react-leaflet-japan-arcades.png

Demo Code

You can clone the full code for this tutorial from GitHub and follow along to save typing.

Create a React App

If you don't have an existing React app, it's easy to create one!

npx create-react-app my-app

Install Dependencies

We'll use Leaflet and its React wrapper, React Leaflet as the core map components. react-leaflet-cluster will help us group nearby markers into clusters. You can install these using npm or your preferred package manager.

cd my-app
npm install --save leaflet react-leaflet react-leaflet-cluster

Download Data

We also need some data to visualize! We've already done the work for you and created a JSON file of all the arcades in Japan, which you can download and use in your project.

Import and Setup

Before we get to the maps, you'll need some boilerplate at the top of your component. If you don't import the Leaflet CSS, styling of many elements (most obviously the markers) will break.

import 'leaflet/dist/leaflet.css'
import {MapContainer, Marker, Popup} from 'react-leaflet'
import L from 'leaflet'
import MarkerClusterGroup from "react-leaflet-cluster";
import {MapLibreTileLayer} from "./MapLibreTileLayer.tsx";
import arcades from './arcades.json'

You may also need to include the following JS right after the imports, depending on your webpack configuration. See this GitHub Issue for details.

delete L.Icon.Default.prototype._getIconUrl;

L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  iconUrl: require('leaflet/dist/images/marker-icon.png'),
  shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});

Finally, you'll need to add some CSS to set the height of the map. If the map control doesn't have a specified height, it won't show up at all!

.full-height-map {
  height: 100vh;
}

Add a Map

Now we're ready to start adding a map! In React Leaflet, we do this with the MapContainer component, which we customize with a few attributes. We then add a TileLayer which tells Leaflet where to get the basemap tiles.

Tip

Check out the library for more raster map styles.

What does maxBounds do?

The map parameters mostly have self-explanatory names, but maxBounds deserves a quick explanation. If you don't set this, scrolling east past Japan will "warp" around back to the US (fine), but your markers will not be visible when you get around to Japan again!

<MapContainer
  className="full-height-map"
  center={[38, 139.69222]}
  zoom={6}
  minZoom={3}
  maxZoom={19}
  maxBounds={[[-85.06, -180], [85.06, 180]]}
  scrollWheelZoom={true}>
  <TileLayer
    attribution='&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>'
    url="https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png"
  />
  {/* TODO: Add markers */}
</MapContainer>

Add Some Markers

As part of the tutorial, we've provided Japanese arcade locations in a format called GeoJSON. We won't dive too deep into the details here, but it contains an array of geometric objects called features. Each one contains geometry information (in our case, latitude and longitude) and metadata (the name of the arcade).

We can turn this raw data into markers with the map function, generating a marker for each arcade. We'll even attach a popup that shows up on click/tap. You can put pretty much whatever you want in the popup markup-wise, and can even style them using CSS!

{arcades.features.map((arcade, index) => (
  <Marker
    key={arcade.properties['@id']}
    position={[arcade.geometry.coordinates[1], arcade.geometry.coordinates[0]]}
  >
    <Popup>
      {arcade.properties.name}
      <br />
      {arcade.properties['name:en']}
    </Popup>
  </Marker>
))}

Cluster Markers into Groups

Japan has quite a few arcades and, as you might guess, they tend to be clustered in dense urban areas. Drawing hundreds of markers in a small area isn't particularly efficient for your web browser, nor does it look very good.

We can make our arcade map much nicer by clustering markers into groups, only showing individual markers if there is enough space. All you have to do is wrap the markers in a MarkerClusterGroup. Magic!

<MarkerClusterGroup>
  {/* Markers */}
</MarkerClusterGroup>

Bring it all Together

We now have all the elements for our Japanese arcade map! We've put all the pieces together for you on GitHub to save typing.

You can use the localhost development web server (via npm start) to get started developing your own app right away. No account required!

Next Steps

React Leaflet has a lot of features not covered in this tutorial, including shape layers, draggable markers, and tooltips. Check out their documentation to learn more.

Once your amazing app is ready to move beyond localhost, sign up for a free Stadia Maps account, and we'll walk through the next steps.

Get Started With a Free Account