Ctrl + k

or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-leaflet@5.0.x

docs

index.md
tile.json

tessl/npm-react-leaflet

tessl install tessl/npm-react-leaflet@5.0.3

React components for Leaflet maps

quick-start.mddocs/guides/

Quick Start Guide

Complete walkthrough for getting started with React Leaflet.

Prerequisites

  • Node.js 16+ installed
  • React 19.x project set up
  • Basic understanding of React hooks and components
  • Familiarity with TypeScript (optional but recommended)

Installation

Step 1: Install Packages

npm install react-leaflet leaflet

For TypeScript projects:

npm install -D @types/leaflet

Step 2: Import Leaflet CSS

In your main application file or component:

import "leaflet/dist/leaflet.css";

Important: This CSS import is required for the map to display correctly.

Basic Map Setup

Step 3: Create Your First Map

Create a new component file Map.tsx (or Map.jsx):

import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";

export function Map() {
  return (
    <MapContainer 
      center={[51.505, -0.09]} 
      zoom={13} 
      style={{ height: "400px", width: "100%" }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={[51.505, -0.09]}>
        <Popup>
          A pretty CSS3 popup. <br /> Easily customizable.
        </Popup>
      </Marker>
    </MapContainer>
  );
}

Step 4: Use the Map Component

import { Map } from "./Map";

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

export default App;

Fixing Default Marker Icons

Step 5: Configure Default Icons (Required for Webpack/Vite)

Due to how bundlers handle assets, marker icons may not display correctly. Add this configuration:

import L from "leaflet";
import "leaflet/dist/leaflet.css";
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
import iconRetina from "leaflet/dist/images/marker-icon-2x.png";

let DefaultIcon = L.icon({
  iconUrl: icon,
  iconRetinaUrl: iconRetina,
  shadowUrl: iconShadow,
  iconSize: [25, 41],
  iconAnchor: [12, 41],
  popupAnchor: [1, -34],
  tooltipAnchor: [16, -28],
  shadowSize: [41, 41]
});

L.Marker.prototype.options.icon = DefaultIcon;

Place this in a file that runs once at application startup (e.g., src/leafletSetup.ts), then import it in your main file:

import "./leafletSetup";

Server-Side Rendering (Next.js)

Step 6: Handle SSR (If Using Next.js)

Leaflet doesn't work with server-side rendering. Use dynamic imports:

import dynamic from 'next/dynamic';

const Map = dynamic(() => import('./Map'), {
  ssr: false,
  loading: () => <p>Loading map...</p>
});

export default function Page() {
  return <Map />;
}

Adding Interactivity

Step 7: Add Click Events

import { useMapEvents } from "react-leaflet";
import { useState } from "react";

function LocationMarker() {
  const [position, setPosition] = useState(null);
  
  useMapEvents({
    click(e) {
      setPosition(e.latlng);
    },
  });

  return position === null ? null : (
    <Marker position={position}>
      <Popup>You clicked here</Popup>
    </Marker>
  );
}

// Use in your map:
<MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: "400px" }}>
  <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
  <LocationMarker />
</MapContainer>

Step 8: Dynamic Map Updates

import { useMap } from "react-leaflet";
import { useEffect } from "react";

function ChangeView({ center, zoom }) {
  const map = useMap();
  
  useEffect(() => {
    map.setView(center, zoom);
  }, [map, center, zoom]);
  
  return null;
}

// Usage:
function App() {
  const [center, setCenter] = useState([51.505, -0.09]);
  const [zoom, setZoom] = useState(13);

  return (
    <MapContainer center={center} zoom={zoom} style={{ height: "400px" }}>
      <ChangeView center={center} zoom={zoom} />
      <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
    </MapContainer>
  );
}

Adding Multiple Markers

Step 9: Render Marker List

const locations = [
  { id: 1, position: [51.505, -0.09], title: "Location 1" },
  { id: 2, position: [51.51, -0.1], title: "Location 2" },
  { id: 3, position: [51.49, -0.08], title: "Location 3" },
];

<MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: "400px" }}>
  <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
  {locations.map((loc) => (
    <Marker key={loc.id} position={loc.position}>
      <Popup>{loc.title}</Popup>
    </Marker>
  ))}
</MapContainer>

Adding Shapes

Step 10: Add Circles and Polygons

import { Circle, Polygon } from "react-leaflet";

<MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: "400px" }}>
  <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
  
  {/* Circle with 200m radius */}
  <Circle 
    center={[51.505, -0.09]} 
    radius={200}
    pathOptions={{ color: 'red', fillColor: 'blue', fillOpacity: 0.5 }}
  />
  
  {/* Polygon */}
  <Polygon
    positions={[
      [51.515, -0.09],
      [51.52, -0.1],
      [51.52, -0.12],
    ]}
    pathOptions={{ color: 'purple' }}
  />
</MapContainer>

Common Customizations

Custom Map Styling

<MapContainer 
  center={[51.505, -0.09]} 
  zoom={13}
  style={{ height: "100vh", width: "100%" }}
  scrollWheelZoom={false}
  zoomControl={false}
>
  <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
  <ZoomControl position="bottomright" />
</MapContainer>

Different Tile Providers

// Satellite imagery
<TileLayer
  url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
  attribution='Tiles &copy; Esri'
/>

// Dark theme
<TileLayer
  url="https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"
  attribution='&copy; OpenStreetMap &copy; CARTO'
/>

// Terrain
<TileLayer
  url="https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png"
  attribution='Map data: &copy; OpenStreetMap, SRTM | Map style: &copy; OpenTopoMap'
  maxZoom={17}
/>

Custom Marker Icons

import L from "leaflet";

const customIcon = new L.Icon({
  iconUrl: "/path/to/icon.png",
  iconSize: [32, 32],
  iconAnchor: [16, 32],
  popupAnchor: [0, -32],
});

<Marker position={[51.505, -0.09]} icon={customIcon}>
  <Popup>Custom icon marker</Popup>
</Marker>

Troubleshooting

Map Not Displaying

Problem: Map container is empty or shows gray area.

Solutions:

  1. Ensure Leaflet CSS is imported: import "leaflet/dist/leaflet.css"
  2. Set explicit height on MapContainer: style={{ height: "400px" }}
  3. Verify center and zoom props are provided

Markers Not Appearing

Problem: Markers don't show on the map.

Solutions:

  1. Configure default marker icons (see Step 5)
  2. Verify marker positions are valid coordinates
  3. Check browser console for errors

TypeScript Errors

Problem: Type errors with Leaflet components.

Solutions:

  1. Install types: npm install -D @types/leaflet
  2. Import types: import type { Map, LatLng } from "leaflet"

Next.js Errors

Problem: "window is not defined" or similar SSR errors.

Solutions:

  1. Use dynamic imports with ssr: false (see Step 6)
  2. Ensure map component only renders client-side

Next Steps

Now that you have a basic map working:

  1. Explore Components: Try different vector shapes, controls, and overlays
  2. Learn Hooks: Master useMap and useMapEvents for advanced interactions
  3. Review Examples: Check real-world scenarios for practical patterns
  4. Optimize Performance: Learn about performance best practices
  5. Add Accessibility: Implement accessibility features

Complete Example

Here's a full working example with all the essentials:

import { MapContainer, TileLayer, Marker, Popup, Circle, useMapEvents } from "react-leaflet";
import { useState } from "react";
import "leaflet/dist/leaflet.css";
import "./leafletSetup"; // Icon configuration

function LocationMarker() {
  const [position, setPosition] = useState(null);
  
  useMapEvents({
    click(e) {
      setPosition(e.latlng);
    },
  });

  return position === null ? null : (
    <Marker position={position}>
      <Popup>You clicked here</Popup>
    </Marker>
  );
}

export function InteractiveMap() {
  const locations = [
    { id: 1, position: [51.505, -0.09], title: "London" },
    { id: 2, position: [51.51, -0.1], title: "Westminster" },
  ];

  return (
    <MapContainer 
      center={[51.505, -0.09]} 
      zoom={13} 
      style={{ height: "600px", width: "100%" }}
      scrollWheelZoom={false}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      
      {locations.map((loc) => (
        <Marker key={loc.id} position={loc.position}>
          <Popup>{loc.title}</Popup>
        </Marker>
      ))}
      
      <Circle 
        center={[51.505, -0.09]} 
        radius={500}
        pathOptions={{ color: 'blue', fillColor: 'lightblue', fillOpacity: 0.3 }}
      />
      
      <LocationMarker />
    </MapContainer>
  );
}

Resources

  • API Reference - Complete component documentation
  • Real-World Examples - Practical usage patterns
  • Official React Leaflet Docs
  • Leaflet Documentation