How to use React-Leaflet
Tags: react, javascript, tutorial
Published: 2020-01-08 16:31:55

---
title: How to use React-Leaflet
published: true
date: 2020-01-01 17:00:19 UTC
tags: react,javascript,tutorial
canonical_url: https://blog.logrocket.com/how-to-use-react-leaflet/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/lp11hvcs4ausmj0npakv.png
---
**Written by [Leigh Halliday](https://blog.logrocket.com/author/leighhalliday/)**✏️

Most developers are familiar with Google Maps and MapBox, but both require accounts to use them, and maybe even entering credit card details. What if you wanted an open-source and free alternative? Here’s where [Leaflet](https://leafletjs.com/) steps up to the plate! It’s a light-weight, open-source mapping library that utilizes [OpenStreetMap](https://www.openstreetmap.org/).

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

In this article, we’ll see how to use [React-Leaflet](https://react-leaflet.js.org/) to render Leaflet maps inside of your React app. We’ll show markers with custom icons, and display a popup on the map when clicked. Later, we will see what needs to change to load remote vs local data using [SWR](https://swr.now.sh/).

The source code shown in this article is [available here](https://github.com/leighhalliday/react-leaflet-demo).

{% youtube DZfvr2zguHo %}

## React-Leaflet installation

After adding `react-leaflet` to our `package.json` file, we’ll need to do a couple small things to get our map displaying correctly. Leaflet requires some CSS to render, and you can do that either by including the CSS `link` tag in your `head`, or you can copy/paste the CSS from the file below directly into your project:

```jsx
<link
  rel="stylesheet"
  href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
  crossorigin=""
/>
```

We need to also make sure to set the width/height of `.leaflet-container` that the map renders itself into, otherwise it won’t be visible because the div will have a height of 0px:

```jsx
.leaflet-container {
  width: 100%;
  height: 100vh;
}
```

Once this is done we’re ready to get started! The code below shows the minimal amount required to get a Leaflet map rendering in our React app. We have imported `Map` from `react-leaflet` (along with some other packages we’ll utilize later on), and we’ll return it from our `App` component.

The `Map` component requires that we set a `center` position, which is an array containing latitude and longitude, along with the default zoom level of the map.

You’ll also notice the `TileLayer` component nested inside of `Map`. We are required to give attribution to OpenStreetMap, otherwise, all you’ll see is a grey square on the screen:

```jsx
import React from "react";
import { Map, Marker, Popup, TileLayer } from "react-leaflet";
import { Icon } from "leaflet";
import * as parkData from "./data/skateboard-parks.json";
import "./app.css";

export default function App() {
  return (
    <Map center={[45.4, -75.7]} zoom={12}>
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      />
    </Map>
  );
}
```

## Displaying map markers

To display markers on the map we need some data. Our data comes from the city of Ottawa, containing the [skateboard parks](https://open.ottawa.ca/datasets/skateboard-parks) in the area. We will load this data locally from a JSON file, but to get an idea of what it looks like, here’s an example of two skateparks below:

```jsx
{
  "features": [
    {
      "type": "Feature",
      "properties": {
        "PARK_ID": 960,
        "NAME": "Bearbrook Skateboard Park",
        "DESCRIPTIO": "Flat asphalt surface, 5 components"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-75.3372987731628, 45.383321536272049]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "PARK_ID": 1219,
        "NAME": "Bob MacQuarrie Skateboard Park (SK8 Extreme Park)",
        "DESCRIPTIO": "Flat asphalt surface, 10 components, City run learn to skateboard programs, City run skateboard camps in summer"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-75.546518086577947, 45.467134581917357]
      }
    }
  ]
}
```

With our data in place, we can map through it inside of the `Map` component, returning a `Marker` component for each of the park locations. A `Marker` requires a `position` prop, telling it where to render on the map. This is an array of `[latitude, longitude]`, much like the `center` prop of the `Map`.

In addition to this, I have set up some state. Inside of the `onClick` prop, we will set the `activePark` when a user clicks on the marker. This will be used later to show some information to the user about a specific skatepark in a map popup:

```jsx
export default function App() {
  const [activePark, setActivePark] = React.useState(null);

  return (
    <Map center={[45.4, -75.7]} zoom={12}>
      {parkData.features.map(park => (
        <Marker
          key={park.properties.PARK_ID}
          position={[
            park.geometry.coordinates[1],
            park.geometry.coordinates[0]
          ]}
          onClick={() => {
            setActivePark(park);
          }}
        />
      ))}
    </Map>
  );
}
```

## Displaying map popups

Because we are tracking which skatepark the user has clicked on, if there is an `activePark` in our state, we can show a `Popup`. The `Popup` component shows a little white bubble that can be closed, and much like a `Marker`, we’re required to give it a position so it knows where to render on the map. Inside of the `Popup` we’re able to pass HTML. This can also be styled using CSS, so feel free to change the look and feel to get it looking exactly like you want.

There is an `onClose` prop/event on the `Popup`, allowing us to track when the user closes the popup bubble so we can update the state accordingly.

```jsx
<Map center={[45.4, -75.7]} zoom={12}>
  {activePark && (
    <Popup
      position={[
        activePark.geometry.coordinates[1],
        activePark.geometry.coordinates[0]
      ]}
      onClose={() => {
        setActivePark(null);
      }}
    >
      <div>
        <h2>{activePark.properties.NAME}</h2>
        <p>{activePark.properties.DESCRIPTIO}</p>
      </div>
    </Popup>
  )}
</Map>
```

## Custom marker icons

It is easy to customize marker icons in Leaflet. It is done by first using `Icon`, imported from `leaflet` itself. With that, we can create a new Icon instance, setting the URL location of the image along with its size.

```jsx
import { Icon } from "leaflet";

const skater = new Icon({
  iconUrl: "/skateboarding.svg",
  iconSize: [25, 25]
});
```

The `Marker` component has an `icon` prop which can be set to the `skater` variable that we created.

## Displaying remote data

Using SWR for remote data fetching, we can load our data remotely from an API endpoint. If you have never worked with SWR before, I have an [article/video on how it works in React](https://www.leighhalliday.com/how-does-swr-work). The truth is that once you have the data, how you display it on the map is no different from local data. We are going to display some [crime data](https://data.police.uk/api/crimes-street/all-crime?lat=52.629729&lng=-1.131592&date=2019-10) provided by the UK police.

I have sliced the data to only render the first 100 crimes in the array because when rendering 1000+ markers, the map slows to a crawl:

```jsx
// existing imports + new import for SWR
import useSwr from "swr";

const fetcher = (...args) => fetch(...args).then(response => response.json());

export default function App() {
  const url =
    "https://data.police.uk/api/crimes-street/all-crime?lat=52.629729&lng=-1.131592&date=2019-10";
  const { data, error } = useSwr(url, { fetcher });
  const crimes = data && !error ? data.slice(0, 100) : [];

  return (
    <Map center={[52.6376, -1.135171]} zoom={12}>
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      />

      {crimes.map(crime => (
        <Marker
          key={crime.id}
          position={[crime.location.latitude, crime.location.longitude]}
        />
      ))}
    </Map>
  );
}
```

If you do require thousands of markers, you may want to look at either using Leaflet directly (to see if it can give you some additional performance) or seeing if Google Maps or MapBox are better suited to your needs.

## Conclusion

Leaflet and its React counterpart, React-Leaflet, are a fantastic open-source and free mapping alternative to Google Maps and MapBox, no API key required! It is an easy package to work with and one worth trying out. Leaflet is an extremely light library, coming in at only [40kb](https://bundlephobia.com/result?p=leaflet@1.6.0) of JS, and it is used by industry giants such as [GitHub, Pinterest, and Etsy](https://leafletjs.com/). [Many more examples](https://react-leaflet.js.org/docs/en/examples) can be found on the React-Leaflet website.

* * * 
## Full visibility into production React apps 

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket.](https://www2.logrocket.com/react-performance-monitoring)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/eq752g8qhbffxt3hp9t4.png)

[LogRocket](https://www2.logrocket.com/react-performance-monitoring) is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — [start monitoring for free.](https://www2.logrocket.com/react-performance-monitoring)
* * *

The post [How to use React-Leaflet](https://blog.logrocket.com/how-to-use-react-leaflet/) appeared first on [LogRocket Blog](https://blog.logrocket.com).