Hello, š Today I want to share with you a small tutorial on how to use Leaflet with React.
For this, we are going to make a web app where we can find some tourist places at... Paris! š«š· š„.
You can check the Demo on : https://react-leaflet-example.netlify.app/ š
What is Leaflet?
Leaflet is the most popular open-source library for interactive maps. You can add markers to a map, make a circle, square, line, and much more interesting stuff. Check the documentation for more: https://leafletjs.com/
What we are going to do : š
- Create our project and install all dependencies
- Show a map, centered on Paris
- Show markers on the map
- Add a new marker on the map
- Draw line between markers
For a sake of visibility, I will put only some part of the code in this article, but feel free to check the source code on Github repo
Installation āļø
First of all, let's create and install dependencies for this project.
- Let's create our project with create-react-app
npx create-react-app react-leaflet-example --template typescript
- Install leaflet and react-leaflet
npm i -S leaflet react-leaflet
- Install types (Optional if you are not using typescript):
npm i -D @types/leaflet
Show a Map šŗ
Now that we have installed all we need, let's create a new component called Map. And add the starter code from the documentation.
It uses MapContainer, and we are passing to it some coordinates to center the map to our city.
TileLayer is used to show copyright on the Map
import { MapContainer, TileLayer } from "react-leaflet";
const Map = () => {
const defaultPosition: LatLngExpression = [48.864716, 2.349]; // Paris position
return (
<div className="map__container">
<MapContainer
center={defaultPosition}
zoom={13}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
</div>
);
};
Show markers on the map š
Our map doesn't have any places yet. So let's add some default places. For that, I created an array of places in advance, with those attributes:
import { LatLngExpression } from "leaflet";
export interface Place {
id: string;
picture: string;
title: string;
description: string;
seeMoreLink: string;
position: LatLngExpression;
}
In my application, I use redux to handle state management of places, show preview modal, etc. I skip how to create/use a store with react-redux. You can check the code on githup repo
So let's import our array of places, and use the Marker component for each place. Marker needs as props our place's position. We can also handle events like click to show a place's description.
Check more about Marker's options
import { MapContainer, TileLayer, Marker, Tooltip } from "react-leaflet";
import { LatLngExpression } from "leaflet";
const Map = ({places}) => {
const defaultPosition: LatLngExpression = [48.864716, 2.349]; // Paris position
const showPreview = (place) => {
// show place's description
}
return (
<div className="map__container">
<MapContainer
center={defaultPosition}
zoom={13}
>
{places.map((place: Place) => (
<Marker
key={place.id}
position={place.position} // š
eventHandlers={{ click: () => showPreview(place) }}
>
{/* show place's title on hover the marker */}
<Tooltip>{place.title}</Tooltip>
</Marker>
))}
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
</div>
);
};
Add new marker on the map āš
Cool! Now we have markers on our map, but how to add new places dynamically? Let's say we want to add a new place when we click on the map.
To show a new place on click, we are going to create a new component called AddMarker that will handle this and update the store.
In this component, we are going to use useMapEvents hook.
import { MapContainer, TileLayer, Marker, Tooltip, useMapEvents } from "react-leaflet";
const AddMarker = () => {
const [position, setPosition] = useState(null);
useMapEvents({
click: (e) => {
setPosition(e.latlng); // š add marker
/* CODE TO ADD NEW PLACE TO STORE (check the source code) */
},
});
return position === null ? null : (
<Marker position={position}></Marker>
);
};
const Map = ({places}) => {
/* ... */
return (
<div className="map__container">
<MapContainer
center={defaultPosition}
zoom={13}
>
{/* ... */}
<AddMarker/>
{/* ... */}
</MapContainer>
</div>
);
};
As we visit Paris let's add Paris-Saint-Germain's stadium ā½ļø
So on click, we are showing the form to add a new place :
On save, the new place is added to our map š.
Draw lines āļø
Now that we have learned how to add markers to our map, let's try to draw a line between each marker.
For that, we are going to use Polyline component.
This component needs a list of positions to draw the line. So let's create an array of positions with our places.
I'll use useEffect to create this array only when places change.
const Map = ({ places }) => {
const [polyLineProps, setPolyLineProps] = useState([]);
useEffect(() => {
setPolyLineProps(places.reduce((prev: LatLngExpression[], curr: Place) => {
prev.push(curr.position);
return prev
;
}, []))
}, [places]);
return (
<MapContainer
center={defaultPosition}
zoom={13}
scrollWheelZoom={false}
style={{ height: "100vh" }}
zoomControl={false}
>
{/* ... */}
<Polyline positions={polyLineProps} /> {/* š */}
{/* ... */}
</ MapContainer>
)
}
Conclusion
In this article, we succeed to show a map and interact with it, like adding markers dynamically and drawing a line. To go further you can try to draw a circle or a rectangle.
Hope it helped some of you.
Thanks for reading. š
Source code available on Github š
Top comments (1)
You should avoid react-leaflet library. If you need to render thousands of objects, you perhaps come across performance issues