I am using the following packages for my map:
"leaflet-routing-machine": "^3.2.12",
"leaflet": "^1.7.1",
"react-leaflet": "^2.7.0",
Essentially I have a Routing machine component which I've integrated with my Map and Markers i.e. (upon clicking two points on the map you get the route) you can drag each and the route updates!
However at this point I have a button which resets everything, clears the markers, the associated LAT & LONG. But I just want the route to reset as well.
You can see those previous routes (in beautiful "chartreuse") stay on the map.
Right now I have a function which is supposed to control when the component is visible:
function clearMarkers(){
setIsRoutingDone(false);
}
{isRoutingDone && <Routing isRoutingDone={isRoutingDone} map={map} myMapRef={myMapRef} icon={{startIcon, endIcon}} userLocation={userLocation} coords={{fromLat, fromLon, toLat, toLon}} />}
This is my Routing Machine:
import { MapLayer } from "react-leaflet";
import L from "leaflet";
import "leaflet-routing-machine";
import { withLeaflet } from "react-leaflet";
class Routing extends MapLayer {
constructor(props) {
super(props);
}
createLeafletElement() {
const { map, coords, icon, removeFrom, removeTo } = this.props;
var dStart = L.latLng(coords.fromLat, coords.fromLon);
var dGoal = L.latLng(coords.toLat, coords.toLon);
this.leafletElement = L.Routing.control({
collapsible: true,
lineOptions: {
styles: [{color: 'chartreuse', opacity: 1, weight: 5}]
},
waypoints: [dStart, dGoal],
createMarker: function(i, waypoints, n) {
if (i === 0) {
marker_icon = icon.startIcon;
}
var marker_icon;
if (i === 0) {
marker_icon = icon.startIcon;
}
else if (i == n - 1) {
marker_icon = icon.endIcon
}
var marker = L.marker(i === 0 ? dStart : dGoal,{
draggable: true,
icon: marker_icon
});
return marker;
}
}).addTo(map.leafletElement);
return this.leafletElement.getPlan();
}
updateLeafletElement(props) {
if(this.leafletElement){
if(this.props.isRoutingDone === false){
this.leafletElement.spliceWaypoints(0, 2); // <-- removes your route
}
}
}
}
export default withLeaflet(Routing);
Actually I logged something in the updateLeafletElement
function and zzilch.
And this is my map:
import React, { useState, useEffect, useRef } from 'react'
import { Map, Marker } from 'react-leaflet';
import LocateControl from '../LocateControl/LocateControl.jsx';
import MapboxLayer from '../MapboxLayer/MapboxLayer.jsx';
import Routing from '../RoutingMachine/RoutingMachine.jsx'
export default function MyMap({getAddressFromLatLong, hillfinderFormButtonRef, setCurrentLocation, setCurrentDestination}) {
var myMapRef = useRef();
useEffect(() => {
hillfinderFormButtonRef.current = clearMarkers;
return() => {
hillfinderFormButtonRef.current = null;
}
}, []);
function resetHandler (){
return myMapRef.current();
};
function clearMarkers(){
console.log("markerData ", markerData);
setMarkerData(markerData => [], ...markerData);
setFromLat(fromLat => null);
setFromLon(fromLon => null);
setToLat(toLat => null)
setToLon(toLon => null)
setFrom(from => 0);
setTo(to => 0);
setIsRoutingDone(false);
// setRemoveFrom(removeFrom => null)
// setRemoveTo(removeTo => null)
}
function saveMap(map){
setMap(map);
}
function handleOnLocationFound(e){
setUserLocation(e.latlng)
}
function markerClick(e){
e.originalEvent.view.L.DomEvent.stopPropagation(e)
}
return (
<Map animate={animate} center={userLocation} onClick={setMarkers} onLocationFound={handleOnLocationFound} zoom={zoom} ref={saveMap}>
{markerData && markerData.map((element, index) => {
return (
<Marker
key={index}
marker_index={index}
position={element}
draggable={true}
onClick={markerClick}
onDragend={updateMarker}
icon={element.id === 0 ? startIcon : endIcon}
/>
)
})}
<MapboxLayer
accessToken={MAPBOX_ACCESS_TOKEN}
style="mapbox://styles/mapbox/streets-v9"
/>
<LocateControl startDirectly />
{isRoutingDone && <Routing isRoutingDone={isRoutingDone} map={map} myMapRef={myMapRef} icon={{startIcon, endIcon}} userLocation={userLocation} coords={{fromLat, fromLon, toLat, toLon}} />}
</Map>
)
}
I got rid of the the code that's not important to the problem at hand!
Thanks in advance!
I actually wound up solving it myself!
Think the head scratcher was while react-leaflet has its lifeCycle methods, i.e. createLeaflet, updateLeafletElement you should not forget the regular React life methods!
Not sure if they overlap, but I found adding componentDidMount:
componentDidMount() {
const { map } = this.props;
map.addControl(this.routing);
}
with updateLeafletElement (I'm using the API for the function correctly now) it accepts a fromProps
and toProps
to just check the value of the prop I pass to the Routing Machine...
updateLeafletElement(fromProps, toProps) {
if (toProps.removeRoutingMachine !== false) {
this.routing.setWaypoints([]);
}
}
Finally on unmount, use the removeControl
method on the map
you pass into the Routing Machine to remove the Router-Machine!
import { MapLayer } from 'react-leaflet';
import L from 'leaflet';
import 'leaflet-routing-machine';
import { withLeaflet } from 'react-leaflet';
class Routing extends MapLayer {
constructor(props) {
super(props);
}
createLeafletElement(props) {
const { map, coords, icon } = this.props;
var dStart = L.latLng(coords.fromLat, coords.fromLon);
var dGoal = L.latLng(coords.toLat, coords.toLon);
if (map && !this.routing) {
this.routing = L.Routing.control({
collapsible: true,
position: 'bottomleft',
lineOptions: {
styles: [{ color: 'chartreuse', opacity: 1, weight: 5 }]
},
waypoints: [dStart, dGoal],
createMarker: function(i, waypoints, n) {
var marker_icon;
if (i === 0) {
marker_icon = icon.startIcon;
} else if (i == n - 1) {
marker_icon = icon.endIcon;
}
var marker = L.marker(i === 0 ? dStart : dGoal, {
draggable: true,
icon: marker_icon
});
return marker;
}
});
}
return this.routing.getPlan();
}
componentDidMount() {
const { map } = this.props;
console.log('map ', map);
map.addControl(this.routing);
}
updateLeafletElement(fromProps, toProps) {
if (toProps.removeRoutingMachine !== false) {
this.routing.setWaypoints([]);
}
}
componentWillUnmount() {
this.destroyRouting();
}
destroyRouting() {
if (this.props.map) {
this.props.map.removeControl(this.routing);
}
}
}
export default withLeaflet(Routing);
Hope this helps! FYI: this is the app I'm using the Routing Machine in case you'd like to browse the other integrations...