From 9557eee808c1dfaa1073cff543e4208e7ad757b8 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Sat, 30 Nov 2024 02:52:44 +0000 Subject: [PATCH] Simplify the implementation I was trying to be too smart and this was causing the current page event to lag behind if you continuously drag. Better to let the library do its job. --- src/view/com/pager/Pager.tsx | 34 +++------------------------------- src/view/com/pager/TabBar.tsx | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index b39bb51371..913e581191 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -76,23 +76,13 @@ export const Pager = forwardRef>( [pagerView], ) - const pendingPage = useSharedValue(selectedPage) - const dragPage = useSharedValue(selectedPage) - const dragProgress = useSharedValue(0) const dragState = useSharedValue<'idle' | 'settling' | 'dragging'>('idle') + const dragProgress = useSharedValue(selectedPage) const handlePageScroll = usePagerHandlers( - // These events don't fire exactly the same way on Android and iOS. - // In these handlers we normalize the behavior to have consistent output values. { onPageScroll(e: PagerViewOnPageScrollEventData) { 'worklet' - let {position, offset} = e - if (offset !== 0) { - // Normalize so that we always track the offset according to the - // last settled page from the application point of view. - const offsetFromPage = offset + (position - dragPage.value) - dragProgress.set(offsetFromPage) - } + dragProgress.set(e.offset + e.position) }, onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) { 'worklet' @@ -103,27 +93,10 @@ export const Pager = forwardRef>( } dragState.set(e.pageScrollState) parentOnPageScrollStateChanged?.(e.pageScrollState) - if (e.pageScrollState === 'idle') { - // This is a good time to update the last known settled page. - const page = pendingPage.get() - dragPage.set(page) - dragProgress.set(0) - runOnJS(onPageSelectedJSThread)(page) - } }, onPageSelected(e: PagerViewOnPageSelectedEventData) { 'worklet' - // We don't usually emit the "page selected" event here because it fires - // prematurely on Android. We'll emit it in the idle state handler above. - pendingPage.set(e.position) - if (dragState.value === 'idle') { - // However, if we already *are* idle, this event is caused by the initial state. - // Let's fire it here since there will be no scroll state change event later. - const page = e.position - dragPage.set(page) - dragProgress.set(0) - runOnJS(onPageSelectedJSThread)(e.position) - } + runOnJS(onPageSelectedJSThread)(e.position) }, }, [parentOnPageScrollStateChanged], @@ -135,7 +108,6 @@ export const Pager = forwardRef>( selectedPage, onSelect: onTabBarSelect, dragGesture: { - dragPage, dragProgress, dragState, }, diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index 9e596697f0..929582c7c2 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -35,20 +35,20 @@ export function TabBar({ const containerSize = useSharedValue(0) const scrollX = useSharedValue(0) const itemsLength = items.length - const {dragPage, dragProgress, dragState} = dragGesture + const {dragProgress, dragState} = dragGesture // When you swipe the pager, the tabbar should scroll automatically // as you're dragging the page and then even during deceleration. useAnimatedReaction( - () => dragPage.get() + dragProgress.get(), - (nextValue, prevValue) => { + () => dragProgress.get(), + (nextProgress, prevProgress) => { if ( - nextValue !== prevValue && + nextProgress !== prevProgress && dragState.value !== 'idle' && isSyncingScroll.get() === true ) { const offsetPerPage = contentSize.get() - containerSize.get() - const offset = (nextValue / (itemsLength - 1)) * offsetPerPage + const offset = (nextProgress / (itemsLength - 1)) * offsetPerPage scrollTo(scrollElRef, offset, 0, false) return } @@ -69,8 +69,8 @@ export function TabBar({ isSyncingScroll.get() === false ) { const offsetPerPage = contentSize.get() - containerSize.get() - const value = dragPage.get() + dragProgress.get() - const offset = (value / (itemsLength - 1)) * offsetPerPage + const progress = dragProgress.get() + const offset = (progress / (itemsLength - 1)) * offsetPerPage scrollTo(scrollElRef, offset, 0, true) isSyncingScroll.set(true) } @@ -84,8 +84,8 @@ export function TabBar({ 'worklet' if (isSyncingScroll.get() === true) { const offsetPerPage = contentSize.get() - containerSize.get() - const valueDiff = index - dragPage.get() - const offsetDiff = (valueDiff / (itemsLength - 1)) * offsetPerPage + const progressDiff = index - dragProgress.get() + const offsetDiff = (progressDiff / (itemsLength - 1)) * offsetPerPage const offset = scrollX.get() + offsetDiff scrollTo(scrollElRef, offset, 0, true) } @@ -98,7 +98,7 @@ export function TabBar({ itemsLength, scrollElRef, scrollX, - dragPage, + dragProgress, ], )