diff --git a/frontend/src/lib/data-map/DataMap.tsx b/frontend/src/lib/data-map/DataMap.tsx index f5ccf25..4a86016 100644 --- a/frontend/src/lib/data-map/DataMap.tsx +++ b/frontend/src/lib/data-map/DataMap.tsx @@ -1,9 +1,8 @@ import type { MapboxOverlay } from '@deck.gl/mapbox/typed'; import { useMap } from 'react-map-gl/maplibre'; -import { FC, useMemo, useRef } from 'react'; +import { FC, useRef } from 'react'; import { useInteractions } from 'lib/state/interactions/use-interactions'; -import { useTriggerMemo } from 'lib/hooks/use-trigger-memo'; import { useDataLoadTrigger } from 'lib/data-map/use-data-load-trigger'; import { InteractionGroupConfig } from 'lib/data-map/types'; import { DeckGLOverlay } from 'lib/map/DeckGLOverlay'; @@ -40,13 +39,9 @@ function buildLayers( } function useTrigger(viewLayers: ViewLayer[]) { - const dataLoaders = useMemo( - () => - viewLayers - .map((vl) => vl.dataAccessFn?.(vl.styleParams?.colorMap?.fieldSpec)?.dataLoader) - .filter(Boolean), - [viewLayers], - ); + const dataLoaders = viewLayers + .map((vl) => vl.dataAccessFn?.(vl.styleParams?.colorMap?.fieldSpec)?.dataLoader) + .filter(Boolean); return useDataLoadTrigger(dataLoaders); } @@ -61,7 +56,7 @@ export const DataMap: FC<{ const { current: map } = useMap(); const zoom = map.getMap().getZoom(); - const dataLoadTrigger = useTrigger(viewLayers); + useTrigger(viewLayers); const { onHover, onClick, layerFilter, pickingRadius } = useInteractions( viewLayers, @@ -69,11 +64,7 @@ export const DataMap: FC<{ interactionGroups, ); - const layers = useTriggerMemo( - () => buildLayers(viewLayers, viewLayersParams, zoom, firstLabelId), - [viewLayers, viewLayersParams, zoom, firstLabelId], - dataLoadTrigger, - ); + const layers = buildLayers(viewLayers, viewLayersParams, zoom, firstLabelId); return ( [] = []; /** * Based on a list of data loaders extracted from view layers, @@ -12,35 +12,36 @@ import { useTrigger } from '../hooks/use-trigger'; * */ export function useDataLoadTrigger(dataLoaders: DataLoader[]) { - const [dataLoadTrigger, doTriggerDataUpdate] = useTrigger(); - - const previousLoaders = usePrevious(dataLoaders); + const [trigger, setTrigger] = useState(0); + const previousLoaders = usePrevious(dataLoaders) ?? DEFAULT_LOADERS; + const removedLoaders = difference(previousLoaders, dataLoaders); + const addedLoaders = difference(dataLoaders, previousLoaders); useEffect(() => { + function incrementTrigger() { + setTrigger((trigger) => trigger + 1); + } // destroy removed data loaders to free up memory - const removedLoaders = difference(previousLoaders ?? [], dataLoaders); removedLoaders.forEach((dl) => dl.destroy()); - // subscribe to new data loaders to get notified when data is loaded - const addedLoaders = difference(dataLoaders, previousLoaders ?? []); - addedLoaders.forEach((dl) => dl.subscribe(doTriggerDataUpdate)); + // subscribe to new data loaders to trigger an update to the data map when data is loaded + addedLoaders.forEach((dl) => dl.subscribe(incrementTrigger)); // if there was a change in data loaders, trigger an update to the data map if (addedLoaders.length > 0 || removedLoaders.length > 0) { - doTriggerDataUpdate(); + incrementTrigger(); } - }, [dataLoaders, previousLoaders, doTriggerDataUpdate]); + }, [addedLoaders, removedLoaders]); /* store current value of dataLoaders so that we can clean up data on component unmount * this is necessary because we don't want to keep the data loaders around after the component is unmounted */ - const currentLoadersRef = useTrackingRef(dataLoaders); useEffect(() => { return () => { // eslint-disable-next-line react-hooks/exhaustive-deps - currentLoadersRef.current?.forEach((dl) => dl.destroy()); + previousLoaders?.forEach((dl) => dl.destroy()); }; - }, [currentLoadersRef]); + }, []); - return dataLoadTrigger; + return trigger; }