When route is displayed for one mode of transport and i select another mode of transport, the old route stays and i end up with 2 routes displayed.
import './App.css';
import React, { useState, useEffect } from 'react';
import SearchBar from './components/SearchBar';
import {
APIProvider,
Map,
useMapsLibrary,
useMap,
} from "@vis.gl/react-google-maps";
const App = () => {
const [mapVisible, setMapVisible] = useState(false);
const [destinationPlaceID, setDestinationPlaceID] = useState(null);
const [originPlaceID, setOriginPlaceID] = useState(null);
const [modeOfTravel, setModeOfTravel] = useState('DRIVING');
const position = { lat: 1.3397443, lng: 103.7067297 };
// Function to start routing with the selected destination
const startRouting = (placeID) => {
setDestinationPlaceID(placeID);
setMapVisible(true); // Show the map when routing starts
};
// Function to get Place ID from user's coordinates (Returns a Promise)
const getPlaceIdFromCoordinates = (latitude, longitude) => {
return new Promise((resolve, reject) => {
const geocoder = new google.maps.Geocoder();
geocoder.geocode(
{ location: { lat: latitude, lng: longitude } },
(results, status) => {
if (status === google.maps.GeocoderStatus.OK) {
if (results[0]) {
const placeId = results[0].place_id;
resolve(placeId); // Resolve with Place ID
} else {
reject('No results found');
}
} else {
reject('Geocoder failed: ' + status);
}
}
);
});
};
function Directions() {
const map = useMap();
const routesLibrary = useMapsLibrary('routes');
const [directionsService, setDirectionsService] = useState(null);
const [directionsRenderer, setDirectionsRenderer] = useState(null);
const [routes, setRoutes] = useState([]);
const [routeIndex, setRouteIndex] = useState(0);
const selected = routes[routeIndex];
const leg = selected?.legs[0];
useEffect(() => {
console.log("Map Loaded with Zoom:", map.getZoom()); // This will log the initial zoom level
}, [map]);
useEffect(() => {
if (!routesLibrary || !map) return;
setDirectionsService(new routesLibrary.DirectionsService());
setDirectionsRenderer(new routesLibrary.DirectionsRenderer({ map }));
}, [routesLibrary, map]);
// Fetch directions once `originPlaceID` is set
useEffect(() => {
if (!directionsService || !directionsRenderer || !originPlaceID) return;
(async () => {
try {
const response = await directionsService.route({
origin: { placeId: originPlaceID },
destination: { placeId: destinationPlaceID },
travelMode: google.maps.TravelMode[modeOfTravel],
provideRouteAlternatives: true,
});
directionsRenderer.setDirections(response);
setRoutes(response.routes);
setRouteIndex(0);
} catch (error) {
console.error('Error fetching directions:', error);
}
})();
}, [directionsService, directionsRenderer, destinationPlaceID, originPlaceID, modeOfTravel]);
useEffect(() => {
if (!directionsRenderer) return;
directionsRenderer.setRouteIndex(routeIndex);
}, [routeIndex, directionsRenderer]);
if (!leg) return null;
return (
<div className="directions">
<h2 className="mapTitle">{selected.summary}</h2>
<p>{leg.start_address.split(',')[0]} to {leg.end_address.split(',')[0]}</p>
<p>Distance: {leg.distance?.text}</p>
<p>Duration: {leg.duration?.text}</p>
<br></br>
<h2 className="mapTitle">Other Routes</h2>
<ul class="otherRoute">
{routes.map((route, index) => (
<li key={route.summary}>
<button id="listText" onClick={() => setRouteIndex(index)}>{route.summary}</button>
</li>
))}
</ul>
</div>
);
}
// Geolocation effect to get the origin Place ID
useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(async (position) => {
const { latitude, longitude } = position.coords;
try {
const placeId = await getPlaceIdFromCoordinates(latitude, longitude);
setOriginPlaceID(placeId); // Set the origin Place ID
} catch (error) {
console.error('Geocoding error:', error);
}
}, () => {
alert('Geolocation is not supported by this browser.');
});
} else {
alert('Geolocation is not supported by this browser.');
}
}, []);
return (
<div>
<h1>Find and Route</h1>
<SearchBar startRouting={startRouting} />
<label htmlFor="modeOfTravel">Select Mode of Travel:</label>
<select
id="modeOfTravel"
value={modeOfTravel}
onChange={(e) => setModeOfTravel(e.target.value)}
>
<option value="DRIVING">Driving</option>
<option value="WALKING">Walking</option>
<option value="BICYCLING">Bicycling</option>
<option value="TRANSIT">Transit</option>
</select>
{mapVisible && (
<div style={{ height: "100vh", width: "100%" }} id="map">
<APIProvider apiKey={import.meta.env.VITE_GOOGLE_API_KEY}>
<Map
defaultCenter={position}
defaultZoom={15}
options={{
zoomControl: true,
gestureHandling: "auto",
scrollwheel: true,
mapTypeControl:true,
scaleControl:false,
streetViewControl:false,
overviewMapControl:false,
rotateControl:false,
}}
>
{destinationPlaceID && <Directions />}
</Map>
</APIProvider>
</div>
)}
</div>
);
};
export default App;
I have seen lots of solutions suggesting to initialise directionsRenderer as a global variable and using setMap(null) however I cant find a successful way to do it in my code without getting lots of errors.
I also tried setting the route array to an empty array.
The routes for the other transport modes is queried successfully and displays properly but i just cant get rid of the old routes.