diff --git a/src/core/store.ts b/src/core/store.ts index 5c7d0078a..bda44667f 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -112,7 +112,9 @@ export const UPDATE_SCROLL_STATE = 0b0001; /** @internal */ export const UPDATE_SIZE_STATE = 0b0010; /** @internal */ -export const UPDATE_SCROLL_WITH_EVENT = 0b0100; +export const UPDATE_SCROLL_EVENT = 0b0100; +/** @internal */ +export const UPDATE_SCROLL_STOP_EVENT = 0b1000; /** * @internal @@ -179,12 +181,6 @@ export const createVirtualStore = ( jumpCount++; } }; - const updateScrollDirection = (dir: ScrollDirection): boolean => { - const prev = _scrollDirection; - _scrollDirection = dir; - // Return true if scrolling is just started or stopped - return _scrollDirection !== prev; - }; return { _getCache() { @@ -390,7 +386,7 @@ export const createVirtualStore = ( // Ignore until manual scrolling !_isManualScrolling ) { - updateScrollDirection(delta < 0 ? SCROLL_UP : SCROLL_DOWN); + _scrollDirection = delta < 0 ? SCROLL_UP : SCROLL_DOWN; } // TODO This will cause glitch in reverse infinite scrolling. Disable this until better solution is found. @@ -409,14 +405,16 @@ export const createVirtualStore = ( shouldSync = distance > viewportSize; scrollOffset = nextScrollOffset; - mutated = UPDATE_SCROLL_STATE + UPDATE_SCROLL_WITH_EVENT; + mutated = UPDATE_SCROLL_STATE + UPDATE_SCROLL_EVENT; break; } case ACTION_SCROLL_END: { - if (updateScrollDirection(SCROLL_IDLE)) { + mutated = UPDATE_SCROLL_STOP_EVENT; + if (_scrollDirection !== SCROLL_IDLE) { shouldFlushPendingJump = true; - mutated = UPDATE_SCROLL_STATE; + mutated += UPDATE_SCROLL_STATE; } + _scrollDirection = SCROLL_IDLE; _isManualScrolling = false; _smoothScrollRange = null; break; diff --git a/src/react/VGrid.tsx b/src/react/VGrid.tsx index f9355c3a4..c57753ad4 100644 --- a/src/react/VGrid.tsx +++ b/src/react/VGrid.tsx @@ -265,8 +265,6 @@ export const VGrid = forwardRef( const height = vStore._getScrollSize(); const width = hStore._getScrollSize(); const rootRef = useRef(null); - const vScrolling = vScrollDirection !== SCROLL_IDLE; - const hScrolling = hScrollDirection !== SCROLL_IDLE; useIsomorphicLayoutEffect(() => { const root = rootRef[refKey]!; @@ -415,7 +413,9 @@ export const VGrid = forwardRef( ref={rootRef} width={width} height={height} - scrolling={vScrolling || hScrolling} + scrolling={ + vScrollDirection !== SCROLL_IDLE || hScrollDirection !== SCROLL_IDLE + } attrs={useMemo( () => ({ ...viewportAttrs, diff --git a/src/react/VList.tsx b/src/react/VList.tsx index 60ba76280..300dd77d7 100644 --- a/src/react/VList.tsx +++ b/src/react/VList.tsx @@ -8,7 +8,7 @@ import { useEffect, } from "react"; import { - UPDATE_SCROLL_WITH_EVENT, + UPDATE_SCROLL_EVENT, ACTION_ITEMS_LENGTH_CHANGE, clampEndIndex, clampStartIndex, @@ -16,6 +16,7 @@ import { UPDATE_SIZE_STATE, UPDATE_SCROLL_STATE, SCROLL_IDLE, + UPDATE_SCROLL_STOP_EVENT, } from "../core/store"; import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; import { exists, max, values } from "../core/utils"; @@ -228,7 +229,6 @@ export const VList = forwardRef( const scrollSize = store._getScrollSize(); const rootRef = useRef(null); - const scrolling = scrollDirection !== SCROLL_IDLE; useIsomorphicLayoutEffect(() => { const root = rootRef[refKey]!; @@ -243,10 +243,13 @@ export const VList = forwardRef( } } ); - const unsubscribeOnScroll = store._subscribe( - UPDATE_SCROLL_WITH_EVENT, + const unsubscribeOnScroll = store._subscribe(UPDATE_SCROLL_EVENT, () => { + onScroll[refKey] && onScroll[refKey](store._getScrollOffset()); + }); + const unsubscribeOnScrollStop = store._subscribe( + UPDATE_SCROLL_STOP_EVENT, () => { - onScroll[refKey] && onScroll[refKey](store._getScrollOffset()); + onScrollStop[refKey] && onScrollStop[refKey](); } ); const cleanupResizer = resizer._observeRoot(root); @@ -254,6 +257,7 @@ export const VList = forwardRef( return () => { unsubscribeStore(); unsubscribeOnScroll(); + unsubscribeOnScrollStop(); cleanupResizer(); cleanupScroller(); }; @@ -266,12 +270,6 @@ export const VList = forwardRef( scroller._fixScrollJump(jump); }, [jumpCount]); - useEffect(() => { - if (!scrolling) { - onScrollStop[refKey] && onScrollStop[refKey](); - } - }, [scrolling]); - useEffect(() => { if (!onRangeChangeProp) return; @@ -341,7 +339,7 @@ export const VList = forwardRef( ref={rootRef} width={isHorizontal ? scrollSize : undefined} height={isHorizontal ? undefined : scrollSize} - scrolling={scrolling} + scrolling={scrollDirection !== SCROLL_IDLE} attrs={useMemo( () => ({ ...viewportAttrs, diff --git a/src/react/WVList.tsx b/src/react/WVList.tsx index 79ca1a7aa..8a24a5ca6 100644 --- a/src/react/WVList.tsx +++ b/src/react/WVList.tsx @@ -15,6 +15,7 @@ import { clampStartIndex, createVirtualStore, SCROLL_IDLE, + UPDATE_SCROLL_STOP_EVENT, } from "../core/store"; import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; import { exists, values } from "../core/utils"; @@ -188,7 +189,6 @@ export const WVList = forwardRef( const scrollSize = store._getTotalSize(); const rootRef = useRef(null); - const scrolling = scrollDirection !== SCROLL_IDLE; useIsomorphicLayoutEffect(() => { const root = rootRef[refKey]!; @@ -203,10 +203,17 @@ export const WVList = forwardRef( } } ); + const unsubscribeOnScrollStop = store._subscribe( + UPDATE_SCROLL_STOP_EVENT, + () => { + onScrollStop[refKey] && onScrollStop[refKey](); + } + ); const cleanupResizer = resizer._observeRoot(root); const cleanupScroller = scroller._observe(root); return () => { unsubscribeStore(); + unsubscribeOnScrollStop(); cleanupResizer(); cleanupScroller(); }; @@ -219,12 +226,6 @@ export const WVList = forwardRef( scroller._fixScrollJump(jump); }, [jumpCount]); - useEffect(() => { - if (!scrolling) { - onScrollStop[refKey] && onScrollStop[refKey](); - } - }, [scrolling]); - useEffect(() => { if (!onRangeChangeProp) return; @@ -278,7 +279,7 @@ export const WVList = forwardRef( ref={rootRef} width={isHorizontal ? scrollSize : undefined} height={isHorizontal ? undefined : scrollSize} - scrolling={scrolling} + scrolling={scrollDirection !== SCROLL_IDLE} attrs={useMemo( () => ({ ...viewportAttrs,