Understanding Leaflet and React: A Guide to Web GIS Applications

Understanding Leaflet and React: A Guide to Web GIS Applications

In this article I will explain how you can create a basic web map with Leaflet and React by using functional components without any third party packages. So i will strongly recommend to have a look at the Leaflet API reference.

What is Leaflet?

Leaflet stands out as a versatile and free JavaScript library, empowering developers to craft seamless Web GIS applications. Leveraging HTML5 and CSS3, Leaflet is compatible with all major web browsers, providing a user-friendly platform for integrating raster and vector data from diverse sources.

Exploring React and Leaflet Integration

Diving deeper into the integration of React and Leaflet components, this article explains the process of creating a web map with fundamental features:

  • Basic map using OpenStreetMap.
  • Visualizing data in GeoJSON format.

Getting Started

First of all you need a react app which you can create with:

npx create-react-app leaflet-react
cd leaflet-react

and you will need to install Leaflet in your project with:

npm install leaflet

After you have installed the package you can import it with import L from "leaflet" into your App.js. The import of the leaflet.css is also important because without it the map-tiles will be misplaced.

//App.js
import React, { useEffect } from "react"
import L from "leaflet"
import "leaflet/dist/leaflet.css"

const App = () => {
  const mapStyles = {
    width: "100%",
    height: "300px",
  }
  const layer = L.tileLayer(
    `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`,
    {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }
  )

  const mapParams = {
    center: [52, 4],
    zoom: 4,
    layers: [layer],
  }

  // This useEffect hook runs when the component is first mounted,
  // similar to componentDidMount() lifecycle method of class-based
  // components:
  useEffect(() => {
    const map = L.map("map", mapParams)
  }, [])

  return (
    <div>
      <div id="map" style={mapStyles} />
    </div>
  )
}

export default App

Since Leaflet doesn't support server-side rendering, the useEffect hook ensures the map rendering post-component mounting.

useEffect(() => {
  L.map("map", mapParams);
}, []);

The "map" parameter is the id of the html-element in which the map will be rendered. With mapParams you can pass some basic parameters as props for the Leaflet map. These parameters can just be created in a object Leaflet API: Map Creation:

const mapParams = {
  center: [0, 0],
  zoom: 0,
  layers: [layer]
};

TileLayers with OpenStreetMap Data are created with L.tileLayer(url, options) (Leaflet API: TileLayer).

const layer = L.tileLayer(`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`, {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  });

Also some basic css in js is created for the map container which makes the map fullscreen and will be passed as style props:

const mapStyles = {
  width: "100%",
  height: "100vh"
 };

In the end you just need html element in which the map will be rendered:

return (
      <div>
        <div id="map" style={mapStyles} />
      </div>
    )

In case something didn't work out as expected you can just clone the following repositiory:

Github Repositiory: https://github.com/dietrichmax/leaflet-react-functional-component Live Demo: https://dietrichmax.github.io/leaflet-react-functional-component/

Adding GeoJSON Data

To add GeoJSON the the map first of all you will need to create a GeoJSON object:

function getGeoJson() {
  return {
    type: "GeometryCollection",
    geometries: [
      {
        type: "Polygon",
        coordinates: [
          [
            [6.000000248663241, 56.000000155530984],
            [7.000000192318055, 56.000000155530984],
            [8.000000135973096, 56.000000155530984],
            [9.000000247266257, 56.000000155530984],
            [10.000000190921071, 56.000000155530984],
            [11.000000134576112, 56.000000155530984],
            [12.000000245869273, 56.000000155530984],
            [12.000000245869273, 55.000000211876],
            [12.000000245869273, 54.00000010058284],
            [12.000000245869273, 53.00000015692797],
            [12.000000245869273, 52.00000021327298],
            [12.000000245869273, 51.00000010197982],
            [12.000000245869273, 50.00000015832478],
            [12.000000245869273, 49.00000004703179],
            [12.000000245869273, 48.000000103376806],
            [11.000000134576112, 48.000000103376806],
            [10.000000190921071, 48.000000103376806],
            [9.000000247266257, 48.000000103376806],
            [8.000000135973096, 48.000000103376806],
            [7.000000192318055, 48.000000103376806],
            [6.000000248663241, 48.000000103376806],
            [6.000000248663241, 49.00000004703179],
            [6.000000248663241, 50.00000015832478],
            [6.000000248663241, 51.00000010197982],
            [6.000000248663241, 52.00000021327298],
            [6.000000248663241, 53.00000015692797],
            [6.000000248663241, 54.00000010058284],
            [6.000000248663241, 55.000000211876],
            [6.000000248663241, 56.000000155530984],
          ],
        ],
      },
    ],
  }
}

The object is wrapped in a function which will return the GeoJSON. You could also fetch a GeoJSON object from somewhere else here.

Then you will need to add the GeoJSON object to the map with:

useEffect(() => {
    const map = L.map("map", mapParams)
    L.geoJSON(getGeoJson()).addTo(map)
  }, [])

And thats it! You map should look now like this:

The code for this component looks like this:

import React, { useEffect } from "react"
import L from "leaflet"
import "leaflet/dist/leaflet.css"

const Map = () => {
  const mapStyles = {
    width: "100%",
    height: "300px",
  }
  const layer = L.tileLayer(
    `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`,
    {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }
  )

  // This useEffect hook runs when the component is first mounted,
  // similar to componentDidMount() lifecycle method of class-based
  // components:
  useEffect(() => {
    const map = L.map("map", mapParams)
    L.geoJSON(getGeoJson()).addTo(map)
  }, [])

  return (
    <div>
      <div id="map" style={mapStyles} />
    </div>
  )
}

export default Map

function getGeoJson() {
  return {
    type: "GeometryCollection",
    geometries: [
      {
        type: "Polygon",
        coordinates: [
          [
            [6.000000248663241, 56.000000155530984],
            [7.000000192318055, 56.000000155530984],
            [8.000000135973096, 56.000000155530984],
            [9.000000247266257, 56.000000155530984],
            [10.000000190921071, 56.000000155530984],
            [11.000000134576112, 56.000000155530984],
            [12.000000245869273, 56.000000155530984],
            [12.000000245869273, 55.000000211876],
            [12.000000245869273, 54.00000010058284],
            [12.000000245869273, 53.00000015692797],
            [12.000000245869273, 52.00000021327298],
            [12.000000245869273, 51.00000010197982],
            [12.000000245869273, 50.00000015832478],
            [12.000000245869273, 49.00000004703179],
            [12.000000245869273, 48.000000103376806],
            [11.000000134576112, 48.000000103376806],
            [10.000000190921071, 48.000000103376806],
            [9.000000247266257, 48.000000103376806],
            [8.000000135973096, 48.000000103376806],
            [7.000000192318055, 48.000000103376806],
            [6.000000248663241, 48.000000103376806],
            [6.000000248663241, 49.00000004703179],
            [6.000000248663241, 50.00000015832478],
            [6.000000248663241, 51.00000010197982],
            [6.000000248663241, 52.00000021327298],
            [6.000000248663241, 53.00000015692797],
            [6.000000248663241, 54.00000010058284],
            [6.000000248663241, 55.000000211876],
            [6.000000248663241, 56.000000155530984],
          ],
        ],
      },
    ],
  }
}

If you are curious how to add some more features like vector layers, some controls or markers have a look at the Leaflet API Reference and much fun playing around with your Leaflet web map created with React and functional components

First published September 23, 2022

    0 Webmentions

    Have you published a response to this? Send me a webmention by letting me know the URL.

    Found no Webmentions yet. Be the first!

    About The Author

    Max
    Max

    Geospatial Developer

    Hi, I'm Max (he/him). I am a geospatial developer, author and cyclist from Rosenheim, Germany. Support me

    0 Virtual Thanks Sent.

    Continue Reading