diff --git a/src/components/ProjectMap/index.tsx b/src/components/ProjectMap/index.tsx index 4c33b69b..0ccfa27a 100644 --- a/src/components/ProjectMap/index.tsx +++ b/src/components/ProjectMap/index.tsx @@ -1,4 +1,9 @@ -import React, { useRef, useCallback } from 'react'; +import React, { + useRef, + useState, + useEffect, + useCallback, +} from 'react'; import { MapContainer, TileLayer, @@ -11,17 +16,45 @@ import GestureHandler from 'components/LeafletGestureHandler'; interface Props { className?: string; children?: React.ReactNode; - geoJSON: GeoJSON.FeatureCollection; + // NOTE: URL to a GeoJSON file which the map fetches and renders. fetch + // supports data: URLs too, so a client-built fallback can be passed the + // same way as a real file URL. + geoJsonUrl: string; } function ProjectMap(props: Props) { const { className, children, - geoJSON, + geoJsonUrl, } = props; const mapRef = useRef(null); + const [geoJson, setGeoJson] = useState(); + + useEffect(() => { + // NOTE: Handle component dismount gracefully + let active = true; + + async function loadGeoJson(url: string) { + try { + const res = await fetch(url); + const data = await res.json(); + if (active) { + setGeoJson(data); + } + } catch (err) { + // eslint-disable-next-line no-console + console.error('Failed fetching map GeoJSON', url, err); + } + } + + loadGeoJson(geoJsonUrl); + + return () => { + active = false; + }; + }, [geoJsonUrl]); const handleGeoJSONAdd = useCallback( (layer: LayerEvent) => { @@ -43,19 +76,24 @@ function ProjectMap(props: Props) { minZoom={1} worldCopyJump > - + {geoJson && ( + + )} - {aoiGeometryFeature && ( + {aoiDownload && (
)}