Play with Maps in React: Online and Offline using Leaflet libraries

In my previous blog, I started with Maps in React applications using MapBox including custom markers. In this blog, I continue to further delve into using maps but this time I picked a different base library – Leaflet, one of the most powerful open source JS Library for interactive maps.

Leaflet is popular due to its simplicity, performance, usability and is further empowered with a huge variety of available plugins which cover almost every functionality you would require to achieve with maps.

In this blog, we will make use of React-Leaflet to include maps, markers, popups and use the react-leaflet-markercluster library to make clusters of the markers in our React application. We will also see how we can make the map work in offline mode, if the user is not connected to the network, using the leaflet-offline library.

We will use the same example of the latitudes and longitudes used in the last blog and show the list of hospitals with the data of Available beds in each.

As always, let’s start with a new app created using create-react-app and then adding to it, the list of dependencies using npm install.

This is how my dependencies in package.json look like after the long running npm install completes.

Don’t miss to include the @next version for react-leaflet-markercluster.

For the Leaflet JS to work as expected we need to include the below links in public/index.html:

If you miss to include the above, you will get broken pieces of map but not a proper complete map view.

With the prerequisites setup in place, we can now proceed with defining our Map component and rendering it in the App.js.

Adding a LeafletMap Component with Markers and PopUps

To define a map, first the below imports are to be included:

The local state is initialised with the required coordinates(latitude, longitude),and zoom options for the map:

Each aspect of the map comprises of different layers which combine to give the complete view of the map. As we include the code, we will have a layer within the map element within which the map will be shown. The APIs return a set of smaller images ( tiles ) that are displayed together one after the other to render the entire map. For every zoom-in or zoom-out, the same behavior gets repeated to render the view. You may have noticed that in the map view also, the map gets rendered piece by piece.

To establish a layer to display the map, we will use a TileLayer element from the react-leaflet library. 

The TileLayer takes two mandatory attributes which include:

  • A url — The url is used to make the API call and get the tiles data for the map.
  • An attribution — This string is used to attribute to the credits from where the url is being used.

Now the map can be rendered as below with Map layered with the TileLayer and further including layers of the marker data with the PopUp data. The data and approach is similar to what was used in the last blog.

The render function looks like below:

The Popups content can be formatted and rendered as below, where marker list is a static array of coordinates and associated data which have to be marked in the map:

The rendered local map looks like below(the center coordinates are from a locality called Madhapur in Hyderabad, India):

You can see all the markers and also when you click on the marker, you can see the PopUp. 

If we want to change the standard markers with some custom image or icon, we can define as below:

The same should be passed into the icon attribute of Marker as below:

With the custom markers, the map looks like below: 

Now, what if we have closely overlapping markers like below?

This is where we need Clusters, to group the closely occuring marker coordinates and show them as a summary count.

Creating Clusters of Markers

We will be using react-leaflet-markercluster and leaflet-markercluster to achieve the cluster functionality. These libraries have already been listed in the initial dependencies so we are ready to put them to use.

To begin let’s import it into our LeafletMap component. We will also import Leaflet to use it to style the cluster icon:

Next we group the markers within the MarkerClusterGroup tag with some additional attributes as below:

Two important points to keep in mind for this library to work here:

  • There should be maxZoom set at the map level: 

  • Include the library specific css in your application in the preferred format(css, scss or js). I included it in my index.css as below:

Now if you zoom out of your map, as the markers start overlapping, you can see the collective counts instead of individual markers.

To incorporate better styling and rendering of the cluster icon, you can add a custom icon function as below:

The same needs to be passed as attributes to the <MarkerClusterGroup> as below:

You can now see your clusters beautifully colored and also how they appear  as you keep zooming out and get separated into markers as you start zooming in as below:

You can further explore the other options of clusters at Leaflet.markercluster

Now the map is fully functional with custom markers, popup and clusters.

 You can fork and play with the code @sandbox

Making the Map available Offline

We know that our map is made up of layers, so now if I want to be able to view and play with my maps, even when I am not connected to the internet, i.e. offline mode, what should I do?

Just add another offline layer! Let’s see how we can do that.

For this ask, we have included the leaflet-offline and localforage in the initial dependencies.

Include the imports as below:

Set up the offline layer after the application mounts  in componentDidMount as below:

This initialises the map offline content as map-id which is the identifier for the container div of the map and adds it to the map.

Now disconnect from the network and check your map.

Our Map is all set to work on and off the network!

Check out the complete code from git here.

Conclusion

In this blog, we covered different aspects of working with maps in React applications, by including clusters and offline render in addition to Custom Markers and Popups, using the base Leaflet JS libraries and several other React wrapper libraries like React-leaflet and react-leaflet-markercluster which make using the underlying Leaflet library, easy to incorporate in the React ecosystem.

References

Comments (1)

hi thanks for this post. it is very informative. I want to ask one question: is it possible that in React js we can set the map before class or function component? Something like this. I am not using react-leaflet also.

import React from ‘react’;
import L from ‘leaflet’;
const style = {
width: “100%”,
height: “800px”
};
let map = L.map(‘map’, {
center: [49.8419, 24.0315],
zoom: 16,
layers: [
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’, {
attribution: ‘© OpenStreetMap contributors’
}),
]
}).addTo(map);;

function App () {
return ;
}
export default App;

Leave a comment

Translate »