Work in progress

This commit is contained in:
Dan Abramov
2023-11-10 13:14:22 +00:00
parent 9beed0ee9a
commit cb14cbb153
+18 -39
View File
@@ -56,12 +56,11 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
) { ) {
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
const [currentPage, setCurrentPage] = React.useState(0) const [currentPage, setCurrentPage] = React.useState(0)
const clampedScrollY = useSharedValue(0)
const [tabBarHeight, setTabBarHeight] = React.useState(0) const [tabBarHeight, setTabBarHeight] = React.useState(0)
const [headerOnlyHeight, setHeaderOnlyHeight] = React.useState(0) const [headerOnlyHeight, setHeaderOnlyHeight] = React.useState(0)
const [isScrolledDown, setIsScrolledDown] = React.useState(false) const [isScrolledDown, setIsScrolledDown] = React.useState(false)
const scrollY = useSharedValue(0)
const headerHeight = headerOnlyHeight + tabBarHeight const headerHeight = headerOnlyHeight + tabBarHeight
const headerOnlyHeightShared = useSharedValue(0)
// capture the header bar sizing // capture the header bar sizing
const onTabBarLayout = React.useCallback( const onTabBarLayout = React.useCallback(
@@ -73,9 +72,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const onHeaderOnlyLayout = React.useCallback( const onHeaderOnlyLayout = React.useCallback(
(evt: LayoutChangeEvent) => { (evt: LayoutChangeEvent) => {
setHeaderOnlyHeight(evt.nativeEvent.layout.height) setHeaderOnlyHeight(evt.nativeEvent.layout.height)
headerOnlyHeightShared.value = evt.nativeEvent.layout.height
}, },
[setHeaderOnlyHeight, headerOnlyHeightShared], [setHeaderOnlyHeight],
) )
// render the the header and tab bar // render the the header and tab bar
@@ -83,11 +81,14 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
() => ({ () => ({
transform: [ transform: [
{ {
translateY: Math.min(-clampedScrollY.value, 0), translateY: Math.min(
Math.min(scrollY.value, headerOnlyHeight) * -1,
0,
),
}, },
], ],
}), }),
[clampedScrollY, headerHeight, tabBarHeight], [scrollY, headerOnlyHeight],
) )
const renderTabBar = React.useCallback( const renderTabBar = React.useCallback(
(props: RenderTabBarFnProps) => { (props: RenderTabBarFnProps) => {
@@ -131,7 +132,6 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const scrollRefs = useSharedValue([]) const scrollRefs = useSharedValue([])
const registerRef = (ref, index) => { const registerRef = (ref, index) => {
lolWut()
scrollRefs.modify(refs => { scrollRefs.modify(refs => {
'worklet' 'worklet'
refs[index] = ref refs[index] = ref
@@ -142,29 +142,16 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
// props to pass into children render functions // props to pass into children render functions
const onScroll = useAnimatedScrollHandler({ const onScroll = useAnimatedScrollHandler({
onScroll(e) { onScroll(e) {
// TODO: We should be able to use headerOnlyHeight directly here, but on the web const nextScrollY = e.contentOffset.y
// there seems is a bug in Reanimated causing state inside this function to be stale. scrollY.value = nextScrollY
clampedScrollY.value = Math.min( if (nextScrollY < headerOnlyHeight) {
e.contentOffset.y,
headerOnlyHeightShared.value,
)
if (e.contentOffset.y < headerOnlyHeightShared.value) {
const refs = scrollRefs.value const refs = scrollRefs.value
for (let i = 0; i < refs.length; i++) { for (let i = 0; i < refs.length; i++) {
scrollTo(refs[i], 0, e.contentOffset.y, false) scrollTo(refs[i], 0, nextScrollY, false)
} }
} }
}, },
}) })
useAnimatedReaction(
() => clampedScrollY.value === headerOnlyHeight,
(nextIsScrolledDown, prevIsScrolledDown) => {
if (nextIsScrolledDown !== prevIsScrolledDown) {
runOnJS(setIsScrolledDown)(nextIsScrolledDown)
}
},
)
const onPageSelectedInner = React.useCallback( const onPageSelectedInner = React.useCallback(
(index: number) => { (index: number) => {
@@ -194,17 +181,13 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
<View key={i} collapsable={false}> <View key={i} collapsable={false}>
<PagerItem <PagerItem
headerHeight={headerHeight} headerHeight={headerHeight}
isReady={
isHeaderReady && headerOnlyHeight > 0 && tabBarHeight > 0
}
isScrolledDown={isScrolledDown} isScrolledDown={isScrolledDown}
onScroll={i === currentPage ? onScroll : noop} onScroll={i === currentPage ? onScroll : noop}
registerRef={ref => { registerRef={ref => registerRef(ref, i)}
lolWut() renderTab={child}
registerRef(ref, i)
}}
renderTab={
isHeaderReady && headerOnlyHeight > 0 && tabBarHeight > 0
? child
: null
}
/> />
</View> </View>
) )
@@ -214,12 +197,9 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
}, },
) )
function lolWut() {
console.log('hi')
}
function PagerItem({ function PagerItem({
headerHeight, headerHeight,
isReady,
isScrolledDown, isScrolledDown,
onScroll, onScroll,
renderTab, renderTab,
@@ -231,10 +211,9 @@ function PagerItem({
onScroll: OnScrollCb onScroll: OnScrollCb
renderTab: ((props: PagerWithHeaderChildParams) => JSX.Element) | null renderTab: ((props: PagerWithHeaderChildParams) => JSX.Element) | null
}) { }) {
lolWut()
const scrollElRef = useAnimatedRef() const scrollElRef = useAnimatedRef()
registerRef(scrollElRef) registerRef(scrollElRef)
if (renderTab == null) { if (!isReady || renderTab == null) {
return null return null
} }
return renderTab({ return renderTab({