Fix pager scroll restoration

This commit is contained in:
Dan Abramov
2023-12-22 02:52:23 +00:00
parent 79eadf5141
commit 72d01685b0
3 changed files with 30 additions and 16 deletions
+1 -4
View File
@@ -521,10 +521,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
// TODO: Clean up? // TODO: Clean up?
navigationRef.current?.addListener('__unsafe_action__', e => { navigationRef.current?.addListener('__unsafe_action__', e => {
if (webFocusedScreen) { if (webFocusedScreen) {
webScrollPositions.set( webScrollPositions.set(webFocusedScreen, window.scrollY)
webFocusedScreen,
Math.round(window.scrollY),
)
} }
}) })
} }
+22 -9
View File
@@ -1,4 +1,5 @@
import React from 'react' import React from 'react'
import {flushSync} from 'react-dom'
import {View} from 'react-native' import {View} from 'react-native'
import {s} from 'lib/styles' import {s} from 'lib/styles'
@@ -28,6 +29,7 @@ export const Pager = React.forwardRef(function PagerImpl(
) { ) {
const [selectedPage, setSelectedPage] = React.useState(initialPage) const [selectedPage, setSelectedPage] = React.useState(initialPage)
const scrollYs = React.useRef([]) const scrollYs = React.useRef([])
const anchorRef = React.useRef(null)
React.useImperativeHandle(ref, () => ({ React.useImperativeHandle(ref, () => ({
setPage: (index: number) => setSelectedPage(index), setPage: (index: number) => setSelectedPage(index),
@@ -35,18 +37,28 @@ export const Pager = React.forwardRef(function PagerImpl(
const onTabBarSelect = React.useCallback( const onTabBarSelect = React.useCallback(
(index: number) => { (index: number) => {
const scrollY = Math.round(window.scrollY) const scrollY = window.scrollY
scrollYs.current[selectedPage] = scrollY let anchorTop = anchorRef.current
? anchorRef.current.getBoundingClientRect().top
: -scrollY
const isSticking = anchorTop <= 5
if (isSticking) {
scrollYs.current[selectedPage] = window.scrollY
} else {
scrollYs.current[selectedPage] = null
}
flushSync(() => {
setSelectedPage(index) setSelectedPage(index)
onPageSelected?.(index) onPageSelected?.(index)
onPageSelecting?.(index) onPageSelecting?.(index)
// if (scrollY >= headerOnlyHeight) { })
window.scrollTo( if (isSticking) {
0, if (scrollYs.current[index]) {
scrollYs.current[index] ?? 0, window.scrollTo(0, scrollYs.current[index])
// Math.max(headerOnlyHeight, scrollYs.current[index] ?? 0), } else {
) window.scrollTo(0, scrollY + anchorTop)
// } }
}
}, },
[selectedPage, setSelectedPage, onPageSelected, onPageSelecting], [selectedPage, setSelectedPage, onPageSelected, onPageSelecting],
) )
@@ -56,6 +68,7 @@ export const Pager = React.forwardRef(function PagerImpl(
{tabBarPosition === 'top' && {tabBarPosition === 'top' &&
renderTabBar({ renderTabBar({
selectedPage, selectedPage,
tabBarAnchor: <View ref={anchorRef} />,
onSelect: onTabBarSelect, onSelect: onTabBarSelect,
})} })}
{React.Children.map(children, (child, i) => ( {React.Children.map(children, (child, i) => (
@@ -6,6 +6,7 @@ import {TabBar} from './TabBar'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {ListMethods} from '../util/List' import {ListMethods} from '../util/List'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
export interface PagerWithHeaderChildParams { export interface PagerWithHeaderChildParams {
headerHeight: number headerHeight: number
@@ -49,6 +50,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
currentPage={currentPage} currentPage={currentPage}
onCurrentPageSelected={onCurrentPageSelected} onCurrentPageSelected={onCurrentPageSelected}
onSelect={props.onSelect} onSelect={props.onSelect}
tabBarAnchor={props.tabBarAnchor}
testID={testID} testID={testID}
/> />
) )
@@ -98,6 +100,7 @@ let PagerTabBar = ({
renderHeader, renderHeader,
onCurrentPageSelected, onCurrentPageSelected,
onSelect, onSelect,
tabBarAnchor,
}: { }: {
currentPage: number currentPage: number
items: string[] items: string[]
@@ -113,6 +116,7 @@ let PagerTabBar = ({
<View style={[!isMobile && styles.headerContainerDesktop, pal.border]}> <View style={[!isMobile && styles.headerContainerDesktop, pal.border]}>
{renderHeader?.()} {renderHeader?.()}
</View> </View>
{tabBarAnchor}
<View <View
style={[ style={[
styles.tabBarContainer, styles.tabBarContainer,