diff --git a/CHANGELOG.md b/CHANGELOG.md index 15f56cb6a..152c65f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Not released +- Improve Widgets calculations sync with tiles [#223](https://github.com/CartoDB/carto-react/pull/223) + ## 1.1.0 (2021-10-29) - Histogram tooltip formatter receiving dataIndex and ticks [#220](https://github.com/CartoDB/carto-react/pull/220) @@ -88,8 +90,6 @@ - Update to latest 8.5.0-alpha.10 deck.gl version [#149](https://github.com/CartoDB/carto-react/pull/149) - Add support to Cloud Native SQL API [#150](https://github.com/CartoDB/carto-react/pull/150) - - ## 1.0.1 (2021-04-12) - Add basic Typescript typings [#136](https://github.com/CartoDB/carto-react/pull/136) diff --git a/packages/react-api/__tests__/hooks/useCartoLayerProps.test.js b/packages/react-api/__tests__/hooks/useCartoLayerProps.test.js index 48834f71e..b19849442 100644 --- a/packages/react-api/__tests__/hooks/useCartoLayerProps.test.js +++ b/packages/react-api/__tests__/hooks/useCartoLayerProps.test.js @@ -34,6 +34,7 @@ describe('useCartoLayerProps', () => { expect(Object.keys(result.current)).toEqual([ 'binary', 'onViewportLoad', + 'fetch', ...COMMON_PROPS ]); }); @@ -51,6 +52,7 @@ describe('useCartoLayerProps', () => { expect(Object.keys(result.current)).toEqual([ 'binary', 'onViewportLoad', + 'fetch', ...COMMON_PROPS ]); }); @@ -68,6 +70,7 @@ describe('useCartoLayerProps', () => { expect(Object.keys(result.current)).toEqual([ 'binary', 'onViewportLoad', + 'fetch', ...COMMON_PROPS ]); }); @@ -87,6 +90,7 @@ describe('useCartoLayerProps', () => { expect(Object.keys(result.current)).toEqual([ 'binary', 'onViewportLoad', + 'fetch', ...COMMON_PROPS ]); }); diff --git a/packages/react-api/src/hooks/useCartoLayerProps.js b/packages/react-api/src/hooks/useCartoLayerProps.js index f8f8c573c..5dc3be117 100644 --- a/packages/react-api/src/hooks/useCartoLayerProps.js +++ b/packages/react-api/src/hooks/useCartoLayerProps.js @@ -6,9 +6,14 @@ import { MAP_TYPES, API_VERSIONS } from '@deck.gl/carto'; export default function useCartoLayerProps({ source, uniqueIdProperty, - viewportFeatures = true + viewportFeatures = true, + viewporFeaturesDebounceTimeout = 500 }) { - const [onViewportLoad, onDataLoad] = useViewportFeatures(source, uniqueIdProperty); + const [onViewportLoad, onDataLoad, fetch] = useViewportFeatures( + source, + uniqueIdProperty, + viewporFeaturesDebounceTimeout + ); let props = {}; @@ -18,7 +23,8 @@ export default function useCartoLayerProps({ ) { props = { binary: true, - onViewportLoad: viewportFeatures ? onViewportLoad : null + onViewportLoad: viewportFeatures ? onViewportLoad : null, + fetch: viewportFeatures ? fetch : null }; } else if (source?.type === MAP_TYPES.QUERY || source?.type === MAP_TYPES.TABLE) { props = { diff --git a/packages/react-api/src/hooks/useViewportFeatures.js b/packages/react-api/src/hooks/useViewportFeatures.js index aec281363..3f4357222 100644 --- a/packages/react-api/src/hooks/useViewportFeatures.js +++ b/packages/react-api/src/hooks/useViewportFeatures.js @@ -1,9 +1,10 @@ -import { useEffect, useCallback, useState, useMemo } from 'react'; +import { useEffect, useCallback, useState, useMemo, useRef } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { setViewportFeaturesReady } from '@carto/react-redux'; import { debounce } from '@carto/react-core'; import { Methods, executeTask } from '@carto/react-workers'; import { MAP_TYPES, API_VERSIONS } from '@deck.gl/carto'; +import { Layer } from '@deck.gl/core'; function isGeoJSONLayer(source) { return isV3(source) && [MAP_TYPES.QUERY, MAP_TYPES.TABLE].includes(source?.type); @@ -16,12 +17,20 @@ function isV3(source) { export default function useViewportFeatures( source, uniqueIdProperty, - debounceTimeOut = 500 + debounceTimeout = 500 ) { const dispatch = useDispatch(); const viewport = useSelector((state) => state.carto.viewport); const [tiles, setTiles] = useState([]); const [isGeoJSONLoaded, setGeoJSONLoaded] = useState(false); + const debounceId = useRef(null); + + const clearDebounce = () => { + if (debounceId.current) { + clearTimeout(debounceId.current); + } + debounceId.current = null; + }; const sourceId = source?.id; @@ -61,8 +70,10 @@ export default function useViewportFeatures( } catch (error) { if (error.name === 'AbortError') return; throw error; + } finally { + clearDebounce(); } - }, debounceTimeOut), + }, debounceTimeout), [setSourceViewportFeaturesReady] ); @@ -80,7 +91,7 @@ export default function useViewportFeatures( if (error.name === 'AbortError') return; throw error; } - }, debounceTimeOut), + }, debounceTimeout), [setSourceViewportFeaturesReady] ); @@ -90,8 +101,14 @@ export default function useViewportFeatures( useEffect(() => { if (sourceId && tiles.length && (!isSourceV3 || isSourceTileset)) { + clearDebounce(); setSourceViewportFeaturesReady(false); - computeFeaturesTileset({ tiles, viewport, uniqueIdProperty, sourceId }); + debounceId.current = computeFeaturesTileset({ + tiles, + viewport, + uniqueIdProperty, + sourceId + }); } }, [ tiles, @@ -128,6 +145,7 @@ export default function useViewportFeatures( }, [source]); const onViewportLoad = useCallback((tiles) => { + clearDebounce(); setTiles(tiles); }, []); @@ -154,5 +172,10 @@ export default function useViewportFeatures( [source, setSourceViewportFeaturesReady] ); - return [onViewportLoad, onDataLoad]; + const fetch = useCallback((arg1, arg2) => { + clearDebounce(); + return Layer.defaultProps.fetch.value(arg1, arg2); + }, []); + + return [onViewportLoad, onDataLoad, fetch]; } diff --git a/packages/react-core/src/utils/debounce.js b/packages/react-core/src/utils/debounce.js index ef4935650..f12aba346 100644 --- a/packages/react-core/src/utils/debounce.js +++ b/packages/react-core/src/utils/debounce.js @@ -6,5 +6,6 @@ export function debounce(fn, ms) { timer = null; fn.apply(this, args); }, ms); + return timer; }; }