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.
This commit is contained in:
Dan Abramov
2024-11-30 02:52:44 +00:00
parent 5e098fa609
commit 9557eee808
2 changed files with 13 additions and 41 deletions
+3 -31
View File
@@ -76,23 +76,13 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
[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<PagerRef, React.PropsWithChildren<Props>>(
}
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<PagerRef, React.PropsWithChildren<Props>>(
selectedPage,
onSelect: onTabBarSelect,
dragGesture: {
dragPage,
dragProgress,
dragState,
},
+10 -10
View File
@@ -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,
],
)