The main idea is im showing several routes on a map,
for each route i render a <DirectionsRenderer component.
however, when i try to remove a DirectionsRenderer it doesn't actually remove it from the map.
what i noticed is that on every render, it renders a couple one on top of the other, so when i remove one, only the top one is removed.
Map component code:
const RoutesResultMap: FC<Props> = ({}) => {
const { GoogleMapProps, rendererProps, mapDivRef, map } = useMap();
return (
<>
<div style={{ height: '90%' }} ref={mapDivRef}>
<MapType2 GoogleMapProps={GoogleMapProps}>
{rendererProps.map((rendererProp, i) => {
return <DirectionsRenderer {...rendererProp} />;
})}
</MapType2>
</div>
</>
);
};
Directions renderer logic - TLDR: Basically creating a (DirectionsRendererProps type) for each route, using a promises array..
const useSimulationDirections = (selectedRoutes: IOptimumRouteData[]) => {
const dispatch = useAppDispatch();
const [rendererProps, setRendererProps] = useState<DirectionsRendererProps[]>([]);
const fetchDirections = () => {
return new Promise((resolve) => {
try {
const requests: { request: google.maps.DirectionsRequest; color: string }[] = [];
const rendererPropsCopy: DirectionsRendererProps[] = [];
const directionsService = new google.maps.DirectionsService();
selectedRoutes.forEach((currRoute) => {
const isCoordsExistOnAllWaypoints = isAllObjectsContainsCoords(currRoute.optimumRoute);
if (isCoordsExistOnAllWaypoints && currRoute.optimumRoute.length > 1) {
const routeLength = currRoute.optimumRoute.length;
const origin = {
lat: currRoute.optimumRoute[0].lat,
lng: currRoute.optimumRoute[0].lng,
};
const destination = {
lat: currRoute.optimumRoute[routeLength - 1].lat,
lng: currRoute.optimumRoute[routeLength - 1].lng,
};
const stopWaypoints = currRoute.optimumRoute.slice(1, -1);
const waypoints = stopWaypoints.map((waypoint): google.maps.DirectionsWaypoint => {
// todo - name
return {
location: { lat: waypoint.lat, lng: waypoint.lng },
stopover: true,
};
});
const request: google.maps.DirectionsRequest = {
origin,
destination,
waypoints,
travelMode: google.maps.TravelMode.DRIVING,
avoidTolls: true,
drivingOptions: {
departureTime,
trafficModel: google.maps.TrafficModel.OPTIMISTIC,
},
};
requests.push({ request, color: getColorByRoute(currRoute, []) });
}
});
const serviceResponseCb: ServiceResponseCallBack = (response, status, color) => {
if (status === 'OK' && response) {
rendererPropsCopy.push({
directions: response,
options: {
suppressMarkers: true,
preserveViewport: true,
polylineOptions: {
strokeColor: color ? color : '#28c2ff',
strokeOpacity: 0.7,
strokeWeight: 7,
},
},
});
}
};
const promises: Promise<google.maps.DirectionsResult>[] = [];
requests.forEach((request) => {
const responsePromise = directionsService.route(request.request, (response, status) =>
serviceResponseCb(response, status, request.color)
);
promises.push(responsePromise);
});
Promise.allSettled(promises).then(() => {
setRendererProps(rendererPropsCopy);
});
} catch (error) {
console.error(error);
setRendererProps([]);
// resolve with -1 to indicate error
resolve(-1);
}
});
};
useEffect(() => {
if (selectedRoutes.length) {
// reset rendererProps
fetchDirections();
} else {
setRendererProps([]);
}
}, [selectedRoutes.length]);
return { rendererProps };
};