React-Leaflet Draw Controls
react-leaflet-draw provides a React component, `EditControl`, that integrates the popular Leaflet.draw plugin into React-Leaflet applications. It allows users to add drawing and editing capabilities for geographic features (polygons, lines, circles, markers) directly on a Leaflet map. The current stable version is 0.21.0. While there isn't a stated release cadence, development appears active, aligning with updates to its peer dependencies like `react-leaflet`. Its key differentiator is providing a declarative React interface for Leaflet.draw's imperative API, simplifying state management and rendering for interactive map editing within a React ecosystem. It relies heavily on `react-leaflet`'s context system to access the underlying Leaflet map instance. The library focuses solely on the draw functionality rather than broader GIS features.
Common errors
-
Error: Children of FeatureGroup must be a Layer.
cause Attempting to render `EditControl` or other non-layer components directly inside a `FeatureGroup` from `react-leaflet` without being properly mounted.fixEnsure `EditControl` and any layers are correctly imported and rendered as valid children of `FeatureGroup`. This error is more likely if `react-leaflet` versions are mismatched. -
TypeError: Cannot read properties of undefined (reading '_getIconUrl')
cause Leaflet's default marker icons are not correctly loaded by your bundler, leading to broken image paths.fixApply the Leaflet icon workaround: `import L from 'leaflet'; delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: '...', iconUrl: '...', shadowUrl: '...' });` pointing to valid image paths. -
Module not found: Error: Can't resolve 'leaflet/dist/leaflet.css'
cause The required Leaflet or Leaflet.draw CSS files are not being imported or found by your build system.fixAdd `import 'leaflet/dist/leaflet.css';` and `import 'leaflet-draw/dist/leaflet.draw.css';` to your application's entry point or relevant component. Verify that `leaflet` and `leaflet-draw` are correctly installed in `node_modules`. -
Uncaught Error: `Map` component is no longer supported. Use `MapContainer` instead.
cause `react-leaflet-draw` v0.21.0 has a peer dependency on `react-leaflet` v5+, which deprecated the `Map` component.fixReplace `<Map>` with `<MapContainer>` in your React-Leaflet application and review `react-leaflet` v5 migration guide for other necessary updates.
Warnings
- breaking Leaflet.draw CSS is not automatically included. You *must* manually import `leaflet.css` and `leaflet.draw.css` or link them via CDN. Neglecting this will result in unstyled and potentially broken UI for the drawing tools.
- gotcha Leaflet's default marker icons often break in bundlers like Webpack or Vite due to incorrect URL resolution. This results in missing marker images for drawn points.
- breaking The `EditControl` component must be rendered inside a `FeatureGroup` component from `react-leaflet`. This `FeatureGroup` acts as the layer where drawn elements are added and from which editable items are managed.
- breaking Version 0.21.0 requires `react-leaflet` ^5.0.0. `react-leaflet` v5 introduced significant breaking changes, notably replacing `Map` with `MapContainer` and changes to layer components. Using `react-leaflet-draw` with older `react-leaflet` versions will lead to rendering errors.
- gotcha When using the `edit` prop, setting `featureGroup: null` is crucial to ensure that only layers within the parent `FeatureGroup` are considered for editing. Omitting this can lead to unexpected behavior or editing of layers outside the intended scope.
Install
-
npm install react-leaflet-draw -
yarn add react-leaflet-draw -
pnpm add react-leaflet-draw
Imports
- EditControl
import EditControl from 'react-leaflet-draw'
import { EditControl } from 'react-leaflet-draw' - MapContainer
import { Map } from 'react-leaflet'import { MapContainer, TileLayer, FeatureGroup } from 'react-leaflet' - EditControlProps
import type { EditControlProps } from 'react-leaflet-draw'
Quickstart
import { MapContainer, TileLayer, FeatureGroup, Circle } from 'react-leaflet';
import { EditControl } from "react-leaflet-draw";
import 'leaflet/dist/leaflet.css';
import 'leaflet-draw/dist/leaflet.draw.css';
// Workaround for missing Leaflet icons in Webpack/Vite
import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png',
iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',
shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png'
});
const MapWithDrawControls = () => {
const _onEdited = (e) => {
e.layers.eachLayer((layer) => {
console.log('Layer edited:', layer.toGeoJSON());
});
};
const _onCreated = (e) => {
const { layerType, layer } = e;
console.log('Layer created:', layerType, layer.toGeoJSON());
};
const _onDeleted = (e) => {
e.layers.eachLayer((layer) => {
console.log('Layer deleted:', layer.toGeoJSON());
});
};
return (
<MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: '500px', width: '100%' }}>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<FeatureGroup>
<EditControl
position='topright'
onEdited={_onEdited}
onCreated={_onCreated}
onDeleted={_onDeleted}
draw={{
rectangle: false, // Disable rectangle drawing
circlemarker: false // Disable circle marker drawing
}}
edit={{
poly: { allowIntersection: false }, // Prevent self-intersections for polygons
featureGroup: null // This ensures only items in the parent FeatureGroup are editable
}}
/>
<Circle center={[51.51, -0.06]} radius={200} />
</FeatureGroup>
</MapContainer>
);
};
export default MapWithDrawControls;