diff --git a/frontend/src/features/stations/components/StationMap.tsx b/frontend/src/features/stations/components/StationMap.tsx index 1ed10e4..f01784d 100644 --- a/frontend/src/features/stations/components/StationMap.tsx +++ b/frontend/src/features/stations/components/StationMap.tsx @@ -82,20 +82,34 @@ export const StationMap: React.FC = ({ }; initMap(); + + // Cleanup: clear markers when component unmounts + return () => { + try { + markers.current.forEach((marker) => marker.setMap(null)); + infoWindows.current.forEach((iw) => iw.close()); + markers.current = []; + infoWindows.current = []; + } catch (err) { + // Silently ignore cleanup errors - they don't affect the user + console.debug('[StationMap] Cleanup error (ignored):', err); + } + }; }, []); // Update markers when stations or saved status changes useEffect(() => { if (!map.current) return; - // Clear old markers and info windows - markers.current.forEach((marker) => marker.setMap(null)); - infoWindows.current.forEach((iw) => iw.close()); - markers.current = []; - infoWindows.current = []; + try { + // Clear old markers and info windows + markers.current.forEach((marker) => marker.setMap(null)); + infoWindows.current.forEach((iw) => iw.close()); + markers.current = []; + infoWindows.current = []; - getGoogleMapsApi(); - let allMarkers: google.maps.Marker[] = []; + getGoogleMapsApi(); + let allMarkers: google.maps.Marker[] = []; // Add station markers stations.forEach((station) => { @@ -132,9 +146,19 @@ export const StationMap: React.FC = ({ allMarkers.push(currentLocationMarker.current); } - // Fit bounds to show all markers - if (allMarkers.length > 0) { - fitBoundsToMarkers(map.current, allMarkers); + // Fit bounds to show all markers + if (allMarkers.length > 0) { + fitBoundsToMarkers(map.current, allMarkers); + } + } catch (error) { + // Ignore DOM errors from Google Maps conflicting with React reconciliation + // This is a known issue when Google Maps removes DOM nodes that React still has references to + if (error instanceof Error && error.message.includes('removeChild')) { + console.warn('[StationMap] Ignoring Google Maps DOM conflict:', error.message); + return; + } + // Re-throw other errors + throw error; } }, [stations, savedPlaceIds, currentLocation, onMarkerClick]); diff --git a/frontend/src/features/stations/utils/maps-loader.ts b/frontend/src/features/stations/utils/maps-loader.ts index 09ab938..937c4d4 100644 --- a/frontend/src/features/stations/utils/maps-loader.ts +++ b/frontend/src/features/stations/utils/maps-loader.ts @@ -51,8 +51,7 @@ export function loadGoogleMaps(): Promise { // Create script tag with callback const script = document.createElement('script'); - script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&loading=async&callback=${callbackName}&libraries=places`; - script.async = true; + script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&callback=${callbackName}&libraries=places`; script.defer = true; script.onerror = () => {