react-leaflet is a set of React components that provide a declarative and idiomatic way to build interactive maps using the Leaflet JavaScript library within a React application. Instead of directly manipulating the Leaflet API, react-leaflet allows developers to describe their maps and their layers using React's component-based structure.
Key Concepts and Features:
1. Declarative Syntax: You define your map's structure and layers using React components like `<MapContainer>`, `<TileLayer>`, `<Marker>`, `<Popup>`, `<Circle>`, `<Polygon>`, etc. This makes the code more readable and maintainable, as it mirrors the visual structure of the map.
2. Component-based: Each Leaflet map object (map itself, tile layers, markers, popups, shapes) has a corresponding React component. These components manage the lifecycle of their underlying Leaflet instances.
3. React Integration: It seamlessly integrates with React's component lifecycle, state management, and props system. When props change, react-leaflet efficiently updates the underlying Leaflet map elements.
4. Context API Usage: The `MapContainer` component creates a Leaflet map instance and makes it available to its children via React Context. This allows child components (like `TileLayer` or `Marker`) to interact with the map without prop drilling.
5. Hooks for Interaction: `react-leaflet` provides useful hooks like `useMap` and `useMapEvents` to gain direct access to the Leaflet map instance and respond to map events (e.g., clicks, zooms) from functional components.
6. Extensible: It's easy to create custom components that wrap Leaflet plugins or extend existing Leaflet functionality.
Why use react-leaflet?
* Simplicity: Abstracts away much of the imperative Leaflet API, allowing you to focus on *what* you want on the map rather than *how* to achieve it.
* React Ecosystem: Fits perfectly within the React ecosystem, leveraging React's strengths for UI development.
* Performance: Designed to be performant by only re-rendering and updating Leaflet elements when necessary.
* Maintainability: Component-based structure leads to more organized and easier-to-debug map code.
Basic Usage Flow:
1. Install `leaflet` and `react-leaflet`.
2. Import `leaflet/dist/leaflet.css` for default map styling.
3. Use `<MapContainer>` as the root component for your map.
4. Add `<TileLayer>` inside `MapContainer` to define the base map (e.g., OpenStreetMap tiles).
5. Place other interactive elements like `<Marker>`, `<Popup>`, `<Circle>` as children of `MapContainer` or other layers.
Example Code
import React from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMapEvents } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
// IMPORTANT: Fix for default marker icon not showing up in Webpack/Create React App
// This is a common issue because Webpack doesn't process image URLs in Leaflet's CSS directly.
// We manually set the default icon path.
import L from 'leaflet';
import icon from 'leaflet/dist/images/marker-icon.png';
import iconRetina from 'leaflet/dist/images/marker-icon-2x.png';
import shadow from 'leaflet/dist/images/marker-shadow.png';
// Create a custom default icon to ensure marker images load correctly
let DefaultIcon = L.icon({
iconUrl: icon,
iconRetinaUrl: iconRetina,
shadowUrl: shadow,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
});
// Assign the custom icon to Leaflet's default marker options
L.Marker.prototype.options.icon = DefaultIcon;
function MapEventsLogger() {
const map = useMapEvents({
click: (e) => {
console.log('Map clicked at:', e.latlng);
// You could add a new marker here, for example
},
zoomend: () => {
console.log('Map zoomed to level:', map.getZoom());
},
});
return null; // This component doesn't render anything itself
}
function MyBasicMap() {
const initialPosition = [51.505, -0.09]; // Latitude, Longitude for London
const zoomLevel = 13;
return (
<div style={{ height: '450px', width: '100%', border: '1px solid #ccc' }}>
<MapContainer
center={initialPosition}
zoom={zoomLevel}
scrollWheelZoom={true}
style={{ height: '100%', width: '100%' }}
>
{/* Add a component to log map events */}
<MapEventsLogger />
{/* Define the base tile layer (OpenStreetMap) */}
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{/* Add a marker with a popup */}
<Marker position={initialPosition}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
{/* You can add more markers, circles, polygons, etc. here */}
<Marker position={[51.51, -0.1]}>
<Popup>Another place!</Popup>
</Marker>
</MapContainer>
</div>
);
}
export default MyBasicMap;








react-leaflet