Leaflet Click to Change State Color Click Again to Change Back
Editor's note : This postal service was last updated on 22 October 2021 to improve code and update whatever outdated information.
Almost developers are familiar with Google Maps and MapBox, but both require accounts to employ them and tin can require a paid subscription for certain features. What if you wanted an open source and free alternative? Here's where Leaflet steps up to the plate!
Leaflet is a lightweight, open source mapping library that utilizes OpenStreetMap, a free editable geographic database.
In this article, we'll meet how to use React Leaflet to render Leaflet maps inside a React app. We'll bear witness markers with custom icons and display a popup on the map when clicked. Later, we will run into what needs to change to load remote vs. local information using SWR.
Getting started
Let's begin by creating a React app, then move into its directory. After that install stable versions of react-leaflet and leaflet with the following commands:
npx create-react-app react-leaflet-demo cd react-leaflet-demo # install react-leaflet and leaflet npm install [email protected] [email protected]
Earlier rendering the app, replace the "browserslist" values in the package.json file with:
"browserslist": [ ">0.2%", "non expressionless", "not op_mini all" ]
Doing so will prevent this error beneath from popping up:
Module parse failed: Unexpected token (10:41) File was processed with these loaders: ./node_modules/babel-loader/lib/index.js Y'all may need an boosted loader to handle the outcome of these loaders. > | useEffect(role updatePathOptions() { > | if (props.pathOptions !== optionsRef.current) { > const options = props.pathOptions ?? {}; > | element.case.setStyle(options); > | optionsRef.current = options; Running npm start should render the app with an affirmative message on your browser.
How to install React Leaflet
Subsequently calculation react-leaflet to our parcel.json file, nosotros must display our map correctly. React Leaflet requires some CSS to render, and we tin either include the CSS link tag in caput or nosotros can copy and paste the CSS from the file beneath direct into the project:
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
We need to too to set the width and pinnacle of .leaflet-container that the map renders itself into, otherwise it won't exist visible because the div will have a acme of 0px:
.leaflet-container { width: 100%; height: 100vh; } Once this is washed, nosotros're prepare to become started! The code below shows the minimal amount required to become a Leaflet map rendering in our React app.
We must import Map from react-leaflet (forth with some other packages that we'll use after), and nosotros'll render it from our App component:
import React, {useState} from "react"; import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'; import './App.css'; import { Icon } from "leaflet"; import * every bit parkData from "./data/skateboard-parks.json"; function App() { return ( <MapContainer centre={[45.4, -75.vii]} zoom={12}scrollWheelZoom={simulated}> <TileLayer url="https://{due south}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution='&re-create; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' /> </MapContainer> ); } export default App; The MapContainer component requires that nosotros gear up a center position, which is an assortment containing latitude and longitude, along with the default zoom level of the map.
You'll too notice the TileLayer component nested inside MapContainer. We are required to give attribution to OpenStreetMap, otherwise, all you'll see is a grey square on the screen:
How exercise you add a marking in Leaflet?
To display markers on the map we demand some data. Our information comes from the city of Ottawa, containing the location of skateboard parks in the area. Allow's load this information locally from a JSON file, but, to become an idea of what information technology looks like, hither's an instance of 2 skateparks below:
{ "features": [ { "blazon": "Characteristic", "properties": { "PARK_ID": 960, "Name": "Bearbrook Skateboard Park", "DESCRIPTIO": "Flat asphalt surface, 5 components" }, "geometry": { "blazon": "Signal", "coordinates": [-75.3372987731628, 45.383321536272049] } }, { "type": "Feature", "properties": { "PARK_ID": 1219, "Proper noun": "Bob MacQuarrie Skateboard Park (SK8 Extreme Park)", "DESCRIPTIO": "Flat asphalt surface, 10 components, City run learn to skateboard programs, City run skateboard camps in summer" }, "geometry": { "type": "Point", "coordinates": [-75.546518086577947, 45.467134581917357] } } ] } With our data in identify, we can map through information technology inside of the MapContainer component, returning a Marking component for each of the park locations. A Marker requires a position prop, telling it where to return on the map.
This is an array of [breadth, longitude], much like the eye prop of MapContainer.
In addition to this, nosotros must set up some land. Inside the onClick prop, we let'due south set the activePark when a user clicks on the marker. Nosotros'll use this later to show some information to the user about a specific skatepark in a map popup:
//App.js export default function App() { const [activePark, setActivePark] = useState(null); return ( <MapContainer center={[45.4, -75.7]} zoom={12} scrollWheelZoom={false}> {parkData.features.map(park => ( <Marking key={park.properties.PARK_ID} position={[ park.geometry.coordinates[1], park.geometry.coordinates[0] ]} onClick={() => { setActivePark(park); }} icon={icon} /> ))} </MapContainer> ); } Displaying map popups with React Leaflet
Because we are tracking which skatepark the user clicks on, if at that place is an activePark in our state, we can show a popup.
The Popup component shows a little white bubble that tin can shut, and much like a Mark, we're required to give it a position so information technology knows where to render on the map. Inside of the Popup nosotros're able to pass HTML.
This can also be styled using CSS, so experience free to change the look and experience to go it looking exactly similar you want.
There is an onClose prop upshot on the Popup, allowing us to track when the user closes the popup bubble so nosotros tin can update the state accordingly:
//App.js <MapContainer center={[45.iv, -75.7]} zoom={12} scrollWheelZoom={false}> {activePark && ( <Popup position={[ activePark.geometry.coordinates[one], activePark.geometry.coordinates[0] ]} onClose={() => { setActivePark(null); }} > <div> <h2>{activePark.properties.Proper noun}</h2> <p>{activePark.properties.DESCRIPTIO}</p> </div> </Popup> )} </MapContainer> Calculation React Leaflet custom marker icons
It is like shooting fish in a barrel to customize mark icons in Leaflet by using Icon, imported from leaflet itself. With that, we can create a new Icon case, setting the URL location of the prototype forth with its size:
import { Icon } from "leaflet"; const skater = new Icon({ iconUrl: "/skateboarding.svg", iconSize: [25, 25] }); The Marker component has an icon prop that can be gear up to the skater variable we created.
Displaying remote information with React Leaflet
Using SWR for remote data fetching, nosotros can load our data remotely from an API endpoint. In one case we have the data, how we display it on the map is no different from displaying local information. To add this concept, we will display some crime information provided by the UK police.
I have sliced the data to only render the first 100 crimes in the array considering rendering more than k markers slows the map:
// existing imports + new import for SWR import useSwr from "swr"; const fetcher = (...args) => fetch(...args).then(response => response.json()); function App() { const url = "https://information.police.united kingdom of great britain and northern ireland/api/crimes-street/all-crime?lat=52.629729&lng=-one.131592&date=2019-10"; const { data, error } = useSwr(url, { fetcher }); const crimes = data && !mistake ? data.slice(0, 100) : []; return ( <MapContainer center={[52.6376, -i.135171]} zoom={12} scrollWheelZoom={fake}> <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{10}/{y}.png" attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' /> {crimes.map(crime => ( <Marking key={law-breaking.id} position={[crime.location.latitude, law-breaking.location.longitude]} /> ))} </MapContainer> ); } export default App; If you do require thousands of markers, you may want to wait at either using Leaflet directly (to see if information technology tin requite you lot some additional performance) or seeing if Google Maps or MapBox are amend suited to your needs.
Conclusion
Leaflet and its React counterpart, React Leaflet, are a fantastic open source and free mapping alternative to Google Maps and MapBox, no API fundamental required! It is an easy package to work with and ane worth trying out.
Leaflet is an extremely light library, coming in at just under 40kb of JavaScript, and it is used past industry giants such as GitHub, Pinterest, and Etsy.
The source code shown in this article is bachelor hither.
Full visibility into production React apps
Debugging React applications tin can be difficult, especially when users experience issues that are hard to reproduce. If you're interested in monitoring and tracking Redux land, automatically surfacing JavaScript errors, and tracking irksome network requests and component load time, endeavor LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and study on what state your awarding was in when an issue occurred. LogRocket also monitors your app's functioning, reporting with metrics similar client CPU load, customer memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you lot debug your React apps — offset monitoring for free.
Source: https://blog.logrocket.com/react-leaflet-tutorial/
0 Response to "Leaflet Click to Change State Color Click Again to Change Back"
Post a Comment