Getting Started with Leaflet.js and React: Rendering a Simple Map
Tags: react, leaflet, webdev, tutorial
Published: 2023-07-24 10:35:40

## Introduction
In this series, we will explore how to leverage Leaflet.js, a powerful open-source JavaScript library, along with React, HTML, and CSS, to create interactive maps as an alternative to Google Maps. Whether you’re a junior or senior-level developer, understanding how to use Leaflet.js can empower you to display location data and build custom map-based applications with ease. In this first article, we’ll start by setting up our development environment and rendering a basic map.

Subsequent articles will dive deeper into the world of interactive mapping, covering topics such as adding markers, enabling smooth zooming, handling click events, working with external data, and customizing polygons and popups.

For this tutorial and beyond, we will be utilizing the following tools:

- [Leaflet](https://leafletjs.com/): 
  _A JavaScript library for interactive maps_
- [React](https://reactjs.org/): 
  _A JavaScript library for building user interfaces_
- [React-Leaflet](https://react-leaflet.js.org/):  _React components for Leaflet maps_

---

## What Is Leaflet?
Leaflet.js is an open-source and lightweight JavaScript library that makes it incredibly easy to create interactive maps for the web.

At about 38k stars, Leaflet.js is one of the leading open-source JavaScript libraries for mobile-friendly interactive maps.

If you’re wondering why it’s named “Leaflet,” think of it as a handy tool to help you draw, display, and navigate through maps like a breeze — just like leaves effortlessly fluttering in the wind.

### Why Choose Leaflet?
1. **Lightweight and Fast:** One of the primary reasons developers love Leaflet is its feather-light weight — weighing in at about 42KB — It’s a compact library, which means your web pages won’t be bogged down by heavy scripts, ensuring a smooth and snappy user experience.
2. **User-Friendly and Intuitive:** Leaflet’s API is refreshingly simple and intuitive, making it a perfect fit for developers of all levels. Whether you’re a seasoned pro or just getting started, you’ll find it easy to grasp and implement.
3. **Customizable and Versatile:** Leaflet may be lightweight, but it packs a punch! It offers a plethora of plugins and extensions that can be seamlessly integrated to tailor your maps according to your specific needs. From displaying markers and polygons to handling interactions, the possibilities are virtually limitless.
4. **Cross-Platform Compatibility:** Maps created with Leaflet can be viewed across various platforms and devices without any hassle. Whether your users are accessing your application on a desktop, smartphone, or tablet, the maps will look and function beautifully.
5. **Active Community and Ongoing Development:** With a passionate and active community of developers and contributors, Leaflet continues to evolve and improve. Updates, bug fixes, and exciting new features are regularly released, ensuring you stay at the forefront of modern mapping technologies.

### How Does Leaflet Work?
Leaflet uses a combination of HTML, CSS, and JavaScript to render maps on your web pages. It takes advantage of the power of modern browsers and relies on popular mapping providers like OpenStreetMap, Mapbox, and others, allowing you to display maps with various styles and data overlays.

### Fun Fact: Leaflet’s “Leaf” Logo!
You might have noticed Leaflet’s playful leaf logo. Besides being adorable, it symbolizes the lightweight nature of the library. Just like a single leaf can flutter effortlessly in the wind, Leaflet’s minimalistic design ensures smooth and swift map interactions for your users.

Now that we’ve introduced the magic of Leaflet.js, let’s roll up our sleeves and dive into the exciting world of interactive mapping with React. Together, we’ll explore how to make stunning map applications that leave a lasting impression on users while having fun on this learning journey!

Ready to map out amazing adventures? Let’s get started!

### But wait..
Before jumping into React, let’s understand the basics of Leaflet through plain html, css and js. For this, we will create a simple example where we will be setting up a Leaflet map, working with markers, and popups.

---

## Creating a Plain HTML, CSS, and JS Example with Leaflet
In this section, we’ll create a simple HTML page that includes the Leaflet.js library and demonstrates how to render a basic map, add a marker, and a popup.

<br/>
### Step 1: Set up the HTML Structure
Open up your favorite text editor and create a new HTML file (e.g., index.html) and set up the basic structure:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Simple Leaflet Map</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
  <style>
    /* Set the map container size */
    #map {
      height: 400px;
      width: 100%;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
  <script src="app.js"></script>
</body>
</html>
```

<br/>
### Step 2: Create the JavaScript File (app.js)
Next, create a new JavaScript file called ‘app.js’ in the same directory as your HTML file. This is where we’ll write the code to render the map, add a marker, and a popup

```js
// Wait for the document to be ready
document.addEventListener('DOMContentLoaded', function () {
  // Create a map instance and set the initial view coordinates and zoom level
  var map = L.map('map').setView([51.505, -0.09], 13);


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


  // Create a marker with popup and add it to the map
  var marker = L.marker([51.505, -0.09]).addTo(map);
  marker.bindPopup("Hello, I'm a marker!").openPopup();
});
```

<br/>
### Output
At this point, if we open our index.html in a browser, we should be able to see a map with a marker.

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krghokjrdo5hyc8nogjm.png)

<br/>
### Okay, what did we just do?

### Creating the Map and Adding a Tile Layer

```js
// Create a map instance and set the initial view coordinates and zoom level
var map = L.map('map').setView([51.505, -0.09], 13);
```

Here, we used the `L.map()` method to create a new map instance and pass in the `ID` of the HTML element ‘`map`’, which is the `<div>` where our map will be rendered.

The `setView()` method sets the initial view of the map, with the specified latitude (51.505) and longitude (-0.09), and a zoom level of 13. The higher the zoom level, the closer the map will be displayed.

```js
// Add a tile layer to the map from OpenStreetMap
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
The attribution option in the tile layer is used to give credit to OpenStreetMap contributors. Providing proper attribution is essential when using map data from third-party sources.
```
<br/>
Above, we used the `L.tileLayer()` method to create a tile layer.

A tile layer is a set of image tiles that make up the map’s visual representation. In this example, we’re using the OpenStreetMap tile layer provided by the URL `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`. The _{s}, {z}, {x}, and {y}_ are placeholders for subdomains, zoom level, and tile coordinates, respectively. Leaflet automatically replaces these placeholders to load the correct tiles as you pan and zoom the map.

The attribution option in the tile layer is used to give credit to [OpenStreetMap](https://www.openstreetmap.org/) contributors. Providing proper attribution is essential when using map data from third-party sources.

### Adding a Marker with a Popup

```js
// Create a marker with popup and add it to the map
var marker = L.marker([51.505, -0.09]).addTo(map);
marker.bindPopup("Hello, I'm a marker!").openPopup();
```

To add a marker to the map, we use the `L.marker()` method and pass in the latitude and longitude as an array [51.505, -0.09]. The marker will be placed at this location on the map.

Next, we bind a **popup** to the marker using the `bindPopup()` method. The popup content is the string “Hello, I’m a marker!”. The `openPopup()` method is then used to display the popup immediately after adding the marker to the map.

### Using Different Tile Layers

Leaflet provides various tile layers that you can use to change the appearance and style of your map. Apart from [OpenStreetMap](https://www.openstreetmap.org/), you can use other providers like [Mapbox](https://www.mapbox.com/), [Stamen](http://maps.stamen.com/), [Esri](https://www.esri.com/en-us/home), and more.

Here’s an example of how to use the Mapbox tile layer:

```js
// Using Mapbox tile layer
L.tileLayer('https://{s}.tiles.mapbox.com/v4/{mapId}/{z}/{x}/{y}.png?access_token={accessToken}', {
  attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a>',
  mapId: 'your-mapbox-map-id', // Replace with your Mapbox map ID
  accessToken: 'your-mapbox-access-token' // Replace with your Mapbox access token
}).addTo(map);
```
To use the Mapbox tile layer, you need to sign up for a [Mapbox](https://www.mapbox.com/) account and obtain an access token and map ID. Replace ‘`your-mapbox-map-id`’ and ‘`your-mapbox-access-token`’ with your actual Mapbox credentials

---

## React-Leaflet
Now we know how to create a map, and add markers using Leaflet and vanilla JavaScript. Let’s see how we can achieve the same results with React

### Prerequisites
Before we dive into the React implementation, make sure you have the following installed on your computer:

1. **Node.js** (latest LTS version) and **npm** (Node Package Manager)
2. A **code editor** of your choice (e.g., Visual Studio Code, Sublime Text, or Atom)

### Setting Up the Development Environment
To begin, open your terminal or command prompt and follow these steps:

1.Create a new React project using Create React App:

```shell
npx create-react-app leaflet-map-app

cd leaflet-map-app
```
2.Install the required dependencies:

```shell
npm install leaflet

npm install react-leaflet
```

3.Now, open the project in your code editor.


### Creating the Simple Map Component
In the `src` folder of your project, create a new file called `SimpleMap.js`. This will be our main React component for rendering the map.

### Setting Up the Map
Inside `SimpleMap.js`, begin by importing the required modules:

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

### Rendering the Map
Now, let’s implement the SimpleMap component and render the map:

```jsx
const SimpleMap = () => {
  const mapRef = useRef(null);
  const latitude = 51.505;
  const longitude = -0.09;

  return ( 
    // Make sure you set the height and width of the map container otherwise the map won't show
      <MapContainer center={[latitude, longitude]} zoom={13} ref={mapRef} style={{height: "100vh", width: "100vw"}}>
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {/* Additional map layers or components can be added here */}
      </MapContainer>
  );
};

export default SimpleMap;
```

**Important!**
`<MapContainer center={[latitude, longitude]} zoom={13} ref={mapRef} style={{height: “100vh”, width: “100vw”}}>`

Make sure to set the height and width of the MapContainer otherwise the map won’t render

### Why Use mapRef:
Using `mapRef` with `useRef` allows us to gain direct access to the Leaflet map instance that is managed by React-Leaflet. This is particularly useful when you need to perform actions on the map that go beyond the scope of standard props or event handling. For instance, you may want to interact with the map programmatically, update the map's center or zoom dynamically, or access Leaflet's underlying API directly.

By using `mapRef`, you have more control and flexibility over the map instance, which comes in handy when implementing more advanced map features or interactions in your application.

We’ll look more into it in subsequent articles.


### The MapContainer component
The `MapContainer` renders a container `<div>` element for the map just as we did in the first example.

### How MapContainer Renders to the DOM:

When you include the `MapContainer` component in your JSX code, it gets rendered to the `DOM` just like any other React component. However, there’s a crucial difference between MapContainer and regular HTML elements:

React-Leaflet uses Leaflet’s core library under the hood, which directly manipulates the DOM to render the map. When the MapContainer component is rendered to the DOM, it creates a <div> element with the specified height and width, which serves as the container for the map.

After the initial render, when React reconciles changes in the Virtual DOM, Leaflet’s core library takes control and efficiently manages the map’s appearance and updates without causing a full re-render of the React components. This approach ensures optimal performance, especially when dealing with interactive maps that require frequent updates.

### Putting It All Together

In the `App.js` file, import the `SimpleMap` component and use it in the main application:


_Remember to install the required packages by running **npm install** in your project directory. Once everything is set up, you can launch your development server with **npm start** and see your map in action by visiting **http://localhost:3000** in your browser._

### Output

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jjsqnl21umdpebi97cg.png)

---

## Limitations of React-Leaflet

While React-Leaflet is undoubtedly a fantastic tool for creating interactive maps, it does come with a few quirky limitations.

Leaflet makes direct calls to the DOM when it is loaded, therefore React Leaflet is not compatible with `server-side rendering`.

The components exposed are abstractions for Leaflet layers, not DOM elements. Some of them have properties that can be updated directly by calling the setters exposed by Leaflet while others should be completely replaced, by setting an unique value on their key property so they are properly handled by React’s algorithm.

**To overcome these challenges, developers have used various approaches, such as:**

1. **Conditional Rendering**: One common approach is to conditionally render the Leaflet components on the client-side only, using techniques like dynamic imports or useEffect hooks to ensure they are only executed on the client after the initial rendering.
2. **Leaflet-Headless**: Some developers have created headless versions of Leaflet, like “`leaflet-headless`,” which allow you to render Leaflet maps on the server without requiring a DOM. However, these solutions may have limitations and might not offer the full set of Leaflet features.


**An example of conditional rendering and a simple solution in [Next.js](https://nextjs.org/):**

```js
import dynamic from 'next/dynamic'

function HomePage() {
  const Map = dynamic(
    () => import("components/map"), // replace "components/map" with your component's location
    { 
      loading: () => <p>A map is loading</p>,
      ssr: false // This line is important. It's what prevents server-side render
    }
  )
  return <Map />
}

export default HomePage
```
<br>

### Further Look into the Docs
If you’re eager to explore more advanced use cases or dive deeper into the properties and functionalities of React-Leaflet components, the official documentation is the place to be! The documentation provides comprehensive information on all the available components, options, and features, allowing you to unleash the full potential of Leaflet within your React applications.

**Link to the Documentation: [React-Leaflet Official Documentation](https://react-leaflet.js.org/)**
<br>

## Explore the Code on GitHub

If you're eager to dive into the code and see the magic behind the maps, the full source code for this article series is available on GitHub! 🚀🔍

**[Check out the code on GitHub](https://github.com/timndichu/mapping-world-with-react-and-leaflet)**

Feel free to explore, experiment, and build upon the examples. Happy coding! 🌟🖥️


## Conclusion

Congratulations on completing the first article of this series! I’m thrilled to embark on this journey of writing developer articles and sharing my knowledge with others. As we’ve seen, using Leaflet.js and React together empowers us to create interactive maps with ease, providing a free and powerful alternative to Google Maps.

In our next article, we’ll delve deeper into the world of interactive mapping by adding markers and enabling smooth zooming on our map. Together, we’ll build a feature-rich application that will be valuable for junior and mid-level developers seeking to master the art of map visualization.

I’m excited about the upcoming topics we’ll cover, and I hope you are too. Through this series, my goal is to help and inspire developers to explore new technologies, unleash their creativity, and ultimately build amazing applications.

Thank you for joining me on this journey, and I can’t wait to share the next part of our series with you. Happy coding, and until next time!