Click Below to subscribe

How To Integrate Leaflet Maps in React 2022

Leaflet is an open-source JavaScript library for mobile-friendly interactive maps. In this tutorial, we will integrate leaflet maps in react using react-leaflet package.

1. Let's install create-react-app package.

npm i -g create-react-app

2. Create a new react project

create-react-app react-leaflet-maps
cd react-leaflet-maps

3. Install leafletreact-leaflet packages inside the project.

npm i leaflet react-leaflet

4. Create folder components inside the src folder. Inside this folder create map.component.jsx file.

import React, { useRef, useState } from "react";
import Leaflet from "leaflet"
import "leaflet/dist/leaflet.css" 
import { MapContainer, TileLayer, Marker, Popup, useMapEvents } from "react-leaflet"
import markerIcon from "leaflet/dist/images/marker-icon.png"
import markerShadow from "leaflet/dist/images/marker-shadow.png"
import markerRetina from "leaflet/dist/images/marker-icon-2x.png"

Leaflet.Icon.Default.mergeOptions({
    iconRetinaUrl: markerRetina,
    iconUrl: markerIcon,
    shadowUrl: markerShadow
});

const MapComponent = () => { 
    const mapRef = useRef();
    const zoom = 16;
    const containerStyle = {
        width: "100%",
        height: "400px"
    }
    const center = {
        lat: 28.626137,
        lng: 79.821603
    }
    const initialMarkers = [
        {
            position: {
                lat: 28.625485,
                lng: 79.821091
            },
            draggable: true
        },
        {
            position: {
                lat: 28.625293,
                lng: 79.817926
            },
            draggable: false
        },
        {
            position: {
                lat: 28.625182,
                lng: 79.81464
            },
            draggable: true
        },
    ];

    const [markers, setMarkers] = useState(initialMarkers);

    const mapClicked = async (event) => {
        console.log(event.latlng.lat, event.latlng.lng)   
    }

    const markerClicked = (marker, index) => {   
        console.log(marker.position.lat, marker.position.lng) 
    }

    const markerDragEnd = (event, index) => {
        console.log(event.lat, event.lng)
    } 

    return (
        <MapContainer
            style={containerStyle}
            center={center}
            zoom={zoom}
            scrollWheelZoom={false}
            ref={mapRef}
        >
            <TileLayer
                attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            <MapContent
                onClick={mapClicked}
            />
            {markers.map((marker, index) => (
                <MarkerContent
                    key={index}
                    position={marker.position}
                    draggable={marker.draggable}
                    onMarkerClick={event => markerClicked(marker, index)}
                    onDragEnd={event => markerDragEnd(event, index)}
                />
            ))}
        </MapContainer>
    );
};

const MapContent = ({ onClick }) => {  
    const map = useMapEvents({
        click: event => onClick(event)
    }) 
    return null;
}

const MarkerContent = (props) => {
    const markerRef = useRef();
    const { position, draggable, onMarkerClick, onDragEnd } = props;  
    
    return <Marker
        position={position}
        draggable={draggable}
        eventHandlers={{
            click: event => onMarkerClick(event),
            dragend: () => onDragEnd(markerRef.current.getLatLng())
        }}
        ref={markerRef}
    >
        <Popup>
            <b>{position.lat}, {position.lng}</b>
        </Popup>
    </Marker>
}

export default MapComponent;

You can easily add/remove markers. also, you can pass additional properties in the marker object based on your requirement.

(a). Add a marker

const allMarkers = [...markers];
const marker = {
    position: {
        lat: 28.625043,
        lng: 79.810135
    }, 
    draggable: true
}
allMarkers.push(marker);
setMarkers(allMarkers)

(b). Remove a marker

Example:- Remove 3rd marker of markers array.

const index = 2;
const filteredMarkers = markers.filter((m, i) => i != index);  
setMarkers(filteredMarkers)

(c). Update marker properties

Example:- Update 3rd marker of markers array.

const index = 2;
const allMarkers = [...markers];
allMarkers[index]= { ...allMarkers[index], position: { lat: 28.625043, lng: 79.810135 } };
setMarkers(allMarkers)

5. Open the App.js file and make the following changes.

import React from "react";
import "./App.css";
import MapComponent from "./components/map.component";

function App() {
  return (
    <div className="App">
      <h1>React Leaflet Maps</h1>
      <MapComponent/>
    </div>
  );
}

export default App;

6. Finally start the project.

npm start

open http://localhost:3000 in the browser.

Extras:- Reverse Geocoding

7. Install leaflet-control-geocoder npm package.

npm i leaflet-control-geocoder

8. Import leaflet-control-geocoder

import React, { useRef, useState } from "react";
import Leaflet from "leaflet"
import "leaflet/dist/leaflet.css"
import "leaflet-control-geocoder";

9. Create a function.

const getAddress = (lat, lng) => { 
    const geocoder = Leaflet.Control.Geocoder.nominatim();  
    return new Promise((resolve, reject) => {
        geocoder.reverse(
            { lat, lng },
            mapRef.current.getZoom(),
            results => results.length ? resolve(results[0].name) : reject(null)
        );
    })
}

You can use this function by passing lat and lng.

const mapClicked = async (event) => {
    console.log(event.latlng.lat, event.latlng.lng)   
    const address = await getAddress(event.latlng.lat, event.latlng.lng)
    console.log(address)
}

Checkout my full react-leaflet-maps example.

https://github.com/ultimateakash/react-leaflet-maps

If you facing any issues. don't hesitate to comment below. I will be happy to help you.

Thanks.

Leave Your Comment