diff --git a/example/src/AnimatedHeader.tsx b/example/src/AnimatedHeader.tsx
index d1c0de8..82328cd 100644
--- a/example/src/AnimatedHeader.tsx
+++ b/example/src/AnimatedHeader.tsx
@@ -30,8 +30,8 @@ export const Header = () => {
{
translateY: interpolate(
top.value,
- [0, -(height.value || 0 - MIN_HEADER_HEIGHT)],
- [0, (height.value || 0 - MIN_HEADER_HEIGHT) / 2]
+ [0, -(height || 0 - MIN_HEADER_HEIGHT)],
+ [0, (height || 0 - MIN_HEADER_HEIGHT) / 2]
),
},
],
diff --git a/example/src/FlashList.tsx b/example/src/FlashList.tsx
index b0b3d4e..f3dafbf 100644
--- a/example/src/FlashList.tsx
+++ b/example/src/FlashList.tsx
@@ -30,8 +30,8 @@ export const Header = () => {
{
translateY: interpolate(
top.value,
- [0, -(height.value || 0 - MIN_HEADER_HEIGHT)],
- [0, (height.value || 0 - MIN_HEADER_HEIGHT) / 2]
+ [0, -(height || 0 - MIN_HEADER_HEIGHT)],
+ [0, (height || 0 - MIN_HEADER_HEIGHT) / 2]
),
},
],
diff --git a/example/src/MasonryFlashList.tsx b/example/src/MasonryFlashList.tsx
index ee7bcae..42917b3 100644
--- a/example/src/MasonryFlashList.tsx
+++ b/example/src/MasonryFlashList.tsx
@@ -30,8 +30,8 @@ export const Header = () => {
{
translateY: interpolate(
top.value,
- [0, -(height.value || 0 - MIN_HEADER_HEIGHT)],
- [0, (height.value || 0 - MIN_HEADER_HEIGHT) / 2]
+ [0, -(height || 0 - MIN_HEADER_HEIGHT)],
+ [0, (height || 0 - MIN_HEADER_HEIGHT) / 2]
),
},
],
diff --git a/example/src/Shared/Contacts.tsx b/example/src/Shared/Contacts.tsx
index 114188c..850a88e 100644
--- a/example/src/Shared/Contacts.tsx
+++ b/example/src/Shared/Contacts.tsx
@@ -101,11 +101,7 @@ const renderItem = ({ item }: { item: Item }) =>
const ListEmptyComponent = () => {
const { top, height } = Tabs.useHeaderMeasurements()
const translateY = useDerivedValue(() => {
- return interpolate(
- -top.value,
- [0, height.value || 0],
- [-(height.value || 0) / 2, 0]
- )
+ return interpolate(-top.value, [0, height || 0], [-(height || 0) / 2, 0])
}, [height])
const stylez = useAnimatedStyle(() => {
diff --git a/example/src/Shared/ContactsFlashList.tsx b/example/src/Shared/ContactsFlashList.tsx
index cd0f61d..84f0c66 100644
--- a/example/src/Shared/ContactsFlashList.tsx
+++ b/example/src/Shared/ContactsFlashList.tsx
@@ -101,11 +101,7 @@ const renderItem = ({ item }: { item: Item }) =>
const ListEmptyComponent = () => {
const { top, height } = Tabs.useHeaderMeasurements()
const translateY = useDerivedValue(() => {
- return interpolate(
- -top.value,
- [0, height.value || 0],
- [-(height.value || 0) / 2, 0]
- )
+ return interpolate(-top.value, [0, height || 0], [-(height || 0) / 2, 0])
}, [height])
const stylez = useAnimatedStyle(() => {
diff --git a/example/src/Shared/ExampleMasonry.tsx b/example/src/Shared/ExampleMasonry.tsx
index df30bb3..1b7e1b3 100644
--- a/example/src/Shared/ExampleMasonry.tsx
+++ b/example/src/Shared/ExampleMasonry.tsx
@@ -69,11 +69,7 @@ const ItemSeparator = () =>
const ListEmptyComponent = () => {
const { top, height } = Tabs.useHeaderMeasurements()
const translateY = useDerivedValue(() => {
- return interpolate(
- -top.value,
- [0, height.value || 0],
- [-(height.value || 0) / 2, 0]
- )
+ return interpolate(-top.value, [0, height || 0], [-(height || 0) / 2, 0])
}, [height])
const stylez = useAnimatedStyle(() => {
diff --git a/example/src/Shared/SectionContacts.tsx b/example/src/Shared/SectionContacts.tsx
index d4a9789..41d4c95 100644
--- a/example/src/Shared/SectionContacts.tsx
+++ b/example/src/Shared/SectionContacts.tsx
@@ -117,11 +117,7 @@ const renderItem = ({ item }: { item: Item }) =>
const ListEmptyComponent = () => {
const { top, height } = Tabs.useHeaderMeasurements()
const translateY = useDerivedValue(() => {
- return interpolate(
- -top.value,
- [0, height.value || 0],
- [-(height.value || 0) / 2, 0]
- )
+ return interpolate(-top.value, [0, height || 0], [-(height || 0) / 2, 0])
}, [height])
const stylez = useAnimatedStyle(() => {
diff --git a/src/Container.tsx b/src/Container.tsx
index 913baa3..bf9729a 100644
--- a/src/Container.tsx
+++ b/src/Container.tsx
@@ -1,10 +1,5 @@
import React from 'react'
-import {
- LayoutChangeEvent,
- StyleSheet,
- useWindowDimensions,
- View,
-} from 'react-native'
+import { StyleSheet, useWindowDimensions, View } from 'react-native'
import PagerView from 'react-native-pager-view'
import Animated, {
runOnJS,
@@ -15,6 +10,7 @@ import Animated, {
useSharedValue,
withDelay,
withTiming,
+ useFrameCallback,
} from 'react-native-reanimated'
import { Context, TabNameContext } from './Context'
@@ -27,6 +23,7 @@ import {
useContainerRef,
usePageScrollHandler,
useTabProps,
+ useLayoutHeight,
} from './hooks'
import {
CollapsibleProps,
@@ -93,25 +90,29 @@ export const Container = React.memo(
const windowWidth = useWindowDimensions().width
const width = customWidth ?? windowWidth
- const containerHeight = useSharedValue(undefined)
+ const [containerHeight, getContainerLayoutHeight] = useLayoutHeight()
- const tabBarHeight = useSharedValue(
- initialTabBarHeight
- )
+ const [tabBarHeight, getTabBarHeight] =
+ useLayoutHeight(initialTabBarHeight)
- const headerHeight = useSharedValue(
+ const [headerHeight, getHeaderHeight] = useLayoutHeight(
!renderHeader ? 0 : initialHeaderHeight
)
+ const initialIndex = React.useMemo(
+ () =>
+ initialTabName
+ ? tabNamesArray.findIndex((n) => n === initialTabName)
+ : 0,
+ [initialTabName, tabNamesArray]
+ )
- const contentInset = useDerivedValue(() => {
+ const contentInset = React.useMemo(() => {
if (allowHeaderOverscroll) return 0
// necessary for the refresh control on iOS to be positioned underneath the header
// this also adjusts the scroll bars to clamp underneath the header area
- return IS_IOS
- ? (headerHeight.value || 0) + (tabBarHeight.value || 0)
- : 0
- })
+ return IS_IOS ? (headerHeight || 0) + (tabBarHeight || 0) : 0
+ }, [headerHeight, tabBarHeight, allowHeaderOverscroll])
const snappingTo: ContextType['snappingTo'] = useSharedValue(0)
const offset: ContextType['offset'] = useSharedValue(0)
@@ -131,22 +132,16 @@ export const Container = React.memo(
() => tabNamesArray,
[tabNamesArray]
)
- const index: ContextType['index'] = useSharedValue(
- initialTabName
- ? tabNames.value.findIndex((n) => n === initialTabName)
- : 0
- )
+ const index: ContextType['index'] = useSharedValue(initialIndex)
const focusedTab: ContextType['focusedTab'] =
useDerivedValue(() => {
return tabNames.value[index.value]
}, [tabNames])
- const calculateNextOffset = useSharedValue(index.value)
+ const calculateNextOffset = useSharedValue(initialIndex)
const headerScrollDistance: ContextType['headerScrollDistance'] =
useDerivedValue(() => {
- return headerHeight.value !== undefined
- ? headerHeight.value - minHeaderHeight
- : 0
+ return headerHeight !== undefined ? headerHeight - minHeaderHeight : 0
}, [headerHeight, minHeaderHeight])
const indexDecimal: ContextType['indexDecimal'] = useSharedValue(
@@ -167,7 +162,7 @@ export const Container = React.memo(
scrollToImpl(
refMap[name],
0,
- scrollYCurrent.value - contentInset.value,
+ scrollYCurrent.value - contentInset,
false
)
}
@@ -213,6 +208,33 @@ export const Container = React.memo(
[onIndexChange, onTabChange]
)
+ const syncCurrentTabScrollPosition = () => {
+ 'worklet'
+
+ const name = tabNamesArray[index.value]
+ scrollToImpl(
+ refMap[name],
+ 0,
+ scrollYCurrent.value - contentInset,
+ false
+ )
+ }
+
+ /*
+ * We run syncCurrentTabScrollPosition in every frame after the index
+ * changes for about 1500ms because the Lists can be late to accept the
+ * scrollTo event we send. This fixes the issue of the scroll position
+ * jumping when the user changes tab.
+ * */
+ const toggleSyncScrollFrame = (toggle: boolean) =>
+ syncScrollFrame.setActive(toggle)
+ const syncScrollFrame = useFrameCallback(({ timeSinceFirstFrame }) => {
+ syncCurrentTabScrollPosition()
+ if (timeSinceFirstFrame > 1500) {
+ runOnJS(toggleSyncScrollFrame)(false)
+ }
+ }, false)
+
useAnimatedReaction(
() => {
return calculateNextOffset.value
@@ -236,13 +258,14 @@ export const Container = React.memo(
scrollYCurrent.value =
scrollY.value[tabNames.value[index.value]] || 0
}
+ runOnJS(toggleSyncScrollFrame)(true)
}
},
[]
)
useAnimatedReaction(
- () => headerHeight.value,
+ () => headerHeight,
(_current, prev) => {
if (prev === undefined) {
// sync scroll if we started with undefined header height
@@ -267,32 +290,6 @@ export const Container = React.memo(
}
}, [revealHeaderOnScroll])
- const getHeaderHeight = React.useCallback(
- (event: LayoutChangeEvent) => {
- const height = event.nativeEvent.layout.height
- if (headerHeight.value !== height) {
- headerHeight.value = height
- }
- },
- [headerHeight]
- )
-
- const getTabBarHeight = React.useCallback(
- (event: LayoutChangeEvent) => {
- const height = event.nativeEvent.layout.height
- if (tabBarHeight.value !== height) tabBarHeight.value = height
- },
- [tabBarHeight]
- )
-
- const onLayout = React.useCallback(
- (event: LayoutChangeEvent) => {
- const height = event.nativeEvent.layout.height
- if (containerHeight.value !== height) containerHeight.value = height
- },
- [containerHeight]
- )
-
const onTabPress = React.useCallback(
(name: TabName) => {
const i = tabNames.value.findIndex((n) => n === name)
@@ -302,7 +299,7 @@ export const Container = React.memo(
runOnUI(scrollToImpl)(
ref,
0,
- headerScrollDistance.value - contentInset.value,
+ headerScrollDistance.value - contentInset,
true
)
} else {
@@ -313,11 +310,14 @@ export const Container = React.memo(
[containerRef, refMap, contentInset]
)
- React.useEffect(() => {
- if (index.value >= tabNamesArray.length) {
- onTabPress(tabNamesArray[tabNamesArray.length - 1])
+ useAnimatedReaction(
+ () => tabNamesArray.length,
+ (tabLength) => {
+ if (index.value >= tabLength) {
+ runOnJS(onTabPress)(tabNamesArray[tabLength - 1])
+ }
}
- }, [index.value, onTabPress, tabNamesArray])
+ )
const pageScrollHandler = usePageScrollHandler({
onPageScroll: (e) => {
@@ -381,7 +381,7 @@ export const Container = React.memo(
>
diff --git a/src/FlashList.tsx b/src/FlashList.tsx
index 886dd82..9ce60da 100644
--- a/src/FlashList.tsx
+++ b/src/FlashList.tsx
@@ -11,7 +11,6 @@ import Animated, {
import {
useChainCallback,
useCollapsibleStyle,
- useConvertAnimatedToValue,
useScrollHandlerY,
useSharedAnimatedRef,
useTabNameContext,
@@ -118,16 +117,14 @@ function FlashListImpl(
[progressViewOffset, refreshControl]
)
- const contentInsetValue = useConvertAnimatedToValue(contentInset)
-
const memoContentInset = React.useMemo(
- () => ({ top: contentInsetValue }),
- [contentInsetValue]
+ () => ({ top: contentInset }),
+ [contentInset]
)
const memoContentOffset = React.useMemo(
- () => ({ x: 0, y: -contentInsetValue }),
- [contentInsetValue]
+ () => ({ x: 0, y: -contentInset }),
+ [contentInset]
)
const memoContentContainerStyle = React.useMemo(
diff --git a/src/FlatList.tsx b/src/FlatList.tsx
index 4c82d95..e7a6981 100644
--- a/src/FlatList.tsx
+++ b/src/FlatList.tsx
@@ -6,7 +6,6 @@ import {
useAfterMountEffect,
useChainCallback,
useCollapsibleStyle,
- useConvertAnimatedToValue,
useScrollHandlerY,
useSharedAnimatedRef,
useTabNameContext,
@@ -79,16 +78,14 @@ function FlatListImpl(
[progressViewOffset, refreshControl]
)
- const contentInsetValue = useConvertAnimatedToValue(contentInset)
-
const memoContentInset = React.useMemo(
- () => ({ top: contentInsetValue }),
- [contentInsetValue]
+ () => ({ top: contentInset }),
+ [contentInset]
)
const memoContentOffset = React.useMemo(
- () => ({ x: 0, y: -contentInsetValue }),
- [contentInsetValue]
+ () => ({ x: 0, y: -contentInset }),
+ [contentInset]
)
const memoContentContainerStyle = React.useMemo(
diff --git a/src/Lazy.tsx b/src/Lazy.tsx
index 576bf70..583c28d 100644
--- a/src/Lazy.tsx
+++ b/src/Lazy.tsx
@@ -37,15 +37,6 @@ export const Lazy: React.FC<{
const name = useTabNameContext()
const { focusedTab, refMap } = useTabsContext()
- /**
- * We start mounted if we are the focused tab, or if props.startMounted is true.
- */
- const startMounted = useSharedValue(
- typeof _startMounted === 'boolean'
- ? _startMounted
- : focusedTab.value === name
- )
-
/**
* We keep track of whether a layout has been triggered
*/
@@ -54,13 +45,24 @@ export const Lazy: React.FC<{
/**
* This is used to control when children are mounted
*/
- const [canMount, setCanMount] = React.useState(!!startMounted.value)
+ const [canMount, setCanMount] = React.useState(false)
/**
* Ensure we don't mount after the component has been unmounted
*/
const isSelfMounted = React.useRef(true)
- const opacity = useSharedValue(cancelLazyFadeIn || startMounted.value ? 1 : 0)
+ /**
+ * We start mounted if we are the focused tab, or if props.startMounted is true.
+ */
+ const shouldStartMounted =
+ typeof _startMounted === 'boolean'
+ ? _startMounted
+ : focusedTab.value === name
+ let initialOpacity = 1
+ if (!cancelLazyFadeIn && !shouldStartMounted) {
+ initialOpacity = 0
+ }
+ const opacity = useSharedValue(initialOpacity)
React.useEffect(() => {
return () => {
diff --git a/src/MasonryFlashList.tsx b/src/MasonryFlashList.tsx
index cc5833e..93756ae 100644
--- a/src/MasonryFlashList.tsx
+++ b/src/MasonryFlashList.tsx
@@ -8,7 +8,6 @@ import Animated, {
import {
useChainCallback,
useCollapsibleStyle,
- useConvertAnimatedToValue,
useScrollHandlerY,
useSharedAnimatedRef,
useTabNameContext,
@@ -121,16 +120,14 @@ function MasonryFlashListImpl(
[progressViewOffset, refreshControl]
)
- const contentInsetValue = useConvertAnimatedToValue(contentInset)
-
const memoContentInset = React.useMemo(
- () => ({ top: contentInsetValue }),
- [contentInsetValue]
+ () => ({ top: contentInset }),
+ [contentInset]
)
const memoContentOffset = React.useMemo(
- () => ({ x: 0, y: -contentInsetValue }),
- [contentInsetValue]
+ () => ({ x: 0, y: -contentInset }),
+ [contentInset]
)
const memoContentContainerStyle = React.useMemo(
diff --git a/src/ScrollView.tsx b/src/ScrollView.tsx
index 71260b7..712a65b 100644
--- a/src/ScrollView.tsx
+++ b/src/ScrollView.tsx
@@ -6,7 +6,6 @@ import {
useAfterMountEffect,
useChainCallback,
useCollapsibleStyle,
- useConvertAnimatedToValue,
useScrollHandlerY,
useSharedAnimatedRef,
useTabNameContext,
@@ -91,16 +90,14 @@ export const ScrollView = React.forwardRef<
[progressViewOffset, refreshControl]
)
- const contentInsetValue = useConvertAnimatedToValue(contentInset)
-
const memoContentInset = React.useMemo(
- () => ({ top: contentInsetValue }),
- [contentInsetValue]
+ () => ({ top: contentInset }),
+ [contentInset]
)
const memoContentOffset = React.useMemo(
- () => ({ x: 0, y: -contentInsetValue }),
- [contentInsetValue]
+ () => ({ x: 0, y: -contentInset }),
+ [contentInset]
)
const memoContentContainerStyle = React.useMemo(
diff --git a/src/SectionList.tsx b/src/SectionList.tsx
index 414f649..2bd6b9c 100644
--- a/src/SectionList.tsx
+++ b/src/SectionList.tsx
@@ -6,7 +6,6 @@ import {
useAfterMountEffect,
useChainCallback,
useCollapsibleStyle,
- useConvertAnimatedToValue,
useScrollHandlerY,
useSharedAnimatedRef,
useTabNameContext,
@@ -86,16 +85,14 @@ function SectionListImpl(
[progressViewOffset, refreshControl]
)
- const contentInsetValue = useConvertAnimatedToValue(contentInset)
-
const memoContentInset = React.useMemo(
- () => ({ top: contentInsetValue }),
- [contentInsetValue]
+ () => ({ top: contentInset }),
+ [contentInset]
)
const memoContentOffset = React.useMemo(
- () => ({ x: 0, y: -contentInsetValue }),
- [contentInsetValue]
+ () => ({ x: 0, y: -contentInset }),
+ [contentInset]
)
const memoContentContainerStyle = React.useMemo(
diff --git a/src/hooks.tsx b/src/hooks.tsx
index de81e5c..ba7dffa 100644
--- a/src/hooks.tsx
+++ b/src/hooks.tsx
@@ -22,7 +22,6 @@ import Animated, {
interpolate,
runOnJS,
runOnUI,
- useDerivedValue,
useEvent,
useHandler,
AnimatedRef,
@@ -119,6 +118,20 @@ export function useTabNameContext(): TabName {
return c
}
+export function useLayoutHeight(initialHeight: number = 0) {
+ const [height, setHeight] = useState(initialHeight)
+
+ const getHeight = useCallback(
+ (event: LayoutChangeEvent) => {
+ const latestHeight = event.nativeEvent.layout.height
+ if (latestHeight !== height) {
+ setHeight(latestHeight)
+ }
+ },
+ [height, setHeight]
+ )
+ return [height, getHeight] as const
+}
/**
* Hook to access some key styles that make the whole thing work.
*
@@ -133,15 +146,9 @@ export function useCollapsibleStyle(): CollapsibleStyle {
allowHeaderOverscroll,
minHeaderHeight,
} = useTabsContext()
- const [containerHeightVal, tabBarHeightVal, headerHeightVal] = [
- useConvertAnimatedToValue(containerHeight),
- useConvertAnimatedToValue(tabBarHeight),
- useConvertAnimatedToValue(headerHeight),
- ]
-
const containerHeightWithMinHeader = Math.max(
0,
- (containerHeightVal ?? 0) - minHeaderHeight
+ (containerHeight ?? 0) - minHeaderHeight
)
return useMemo(
@@ -150,24 +157,24 @@ export function useCollapsibleStyle(): CollapsibleStyle {
contentContainerStyle: {
minHeight:
IS_IOS && !allowHeaderOverscroll
- ? containerHeightWithMinHeader - (tabBarHeightVal || 0)
- : containerHeightWithMinHeader + (headerHeightVal || 0),
+ ? containerHeightWithMinHeader - (tabBarHeight || 0)
+ : containerHeightWithMinHeader + (headerHeight || 0),
paddingTop:
IS_IOS && !allowHeaderOverscroll
? 0
- : (headerHeightVal || 0) + (tabBarHeightVal || 0),
+ : (headerHeight || 0) + (tabBarHeight || 0),
},
progressViewOffset:
// on iOS we need the refresh control to be at the top if overscrolling
IS_IOS && allowHeaderOverscroll
? 0
: // on android we need it below the header or it doesn't show because of z-index
- (headerHeightVal || 0) + (tabBarHeightVal || 0),
+ (headerHeight || 0) + (tabBarHeight || 0),
}),
[
allowHeaderOverscroll,
- headerHeightVal,
- tabBarHeightVal,
+ headerHeight,
+ tabBarHeight,
width,
containerHeightWithMinHeader,
]
@@ -231,9 +238,9 @@ export function useScroller() {
if (!ref) return
//! this is left here on purpose to ease troubleshooting (uncomment when necessary)
// console.log(
- // `${_debugKey}, y: ${y}, y adjusted: ${y - contentInset.value}`
+ // `${_debugKey}, y: ${y}, y adjusted: ${y - contentInset}`
// )
- scrollToImpl(ref, x, y - contentInset.value, animated)
+ scrollToImpl(ref, x, y - contentInset, animated)
},
[contentInset]
)
@@ -272,15 +279,8 @@ export const useScrollHandlerY = (name: TabName) => {
(toggle: boolean) => {
'worklet'
enabled.value = toggle
-
- if (toggle) {
- const ref = refMap[name]
- const y = scrollY.value[name] ?? scrollYCurrent.value
-
- scrollTo(ref, 0, y, false, `[${name}] restore scroll position - enable`)
- }
},
- [enabled, name, refMap, scrollTo, scrollY.value, scrollYCurrent.value]
+ [name, refMap, scrollTo]
)
/**
@@ -291,11 +291,6 @@ export const useScrollHandlerY = (name: TabName) => {
*/
const afterDrag = useSharedValue(0)
- const tabIndex = useMemo(
- () => tabNames.value.findIndex((n) => n === name),
- [tabNames, name]
- )
-
const scrollAnimation = useSharedValue(undefined)
useAnimatedReaction(
@@ -359,11 +354,6 @@ export const useScrollHandlerY = (name: TabName) => {
}
}
- const contentHeight = useDerivedValue(() => {
- const tabIndex = tabNames.value.indexOf(name)
- return contentHeights.value[tabIndex] || Number.MAX_VALUE
- }, [])
-
const scrollHandler = useAnimatedScrollHandler(
{
onScroll: (event) => {
@@ -373,11 +363,14 @@ export const useScrollHandlerY = (name: TabName) => {
if (IS_IOS) {
let { y } = event.contentOffset
// normalize the value so it starts at 0
- y = y + contentInset.value
+ y = y + contentInset
+
+ const contentHeight =
+ contentHeights.value[tabNames.value.indexOf(name)] ||
+ Number.MAX_VALUE
+
const clampMax =
- contentHeight.value -
- (containerHeight.value || 0) +
- contentInset.value
+ contentHeight - (containerHeight || 0) + contentInset
// make sure the y value is clamped to the scrollable size (clamps overscrolling)
scrollYCurrent.value = allowHeaderOverscroll
? y
@@ -498,7 +491,7 @@ export const useScrollHandlerY = (name: TabName) => {
if (focusedIsOnTop) {
nextPosition = snappingTo.value
} else if (currIsOnTop) {
- nextPosition = headerHeight.value || 0
+ nextPosition = headerHeight || 0
}
} else if (currIsOnTop || focusedIsOnTop) {
nextPosition = Math.min(focusedScrollY, headerScrollDistance.value)
@@ -512,7 +505,7 @@ export const useScrollHandlerY = (name: TabName) => {
}
}
},
- [revealHeaderOnScroll, refMap, snapThreshold, tabIndex, enabled, scrollTo]
+ [revealHeaderOnScroll, refMap, snapThreshold, enabled, scrollTo]
)
return { scrollHandler, enable }
@@ -586,7 +579,7 @@ export function useAfterMountEffect(
export function useConvertAnimatedToValue(
animatedValue: Animated.SharedValue
) {
- const [value, setValue] = useState(animatedValue.value)
+ const [value, setValue] = useState(animatedValue.value)
useAnimatedReaction(
() => {
@@ -600,7 +593,7 @@ export function useConvertAnimatedToValue(
[value]
)
- return value
+ return value || 0
}
export interface HeaderMeasurements {
@@ -611,7 +604,7 @@ export interface HeaderMeasurements {
/**
* Animated value that represents the height of the header
*/
- height: Animated.SharedValue
+ height: number
}
export function useHeaderMeasurements(): HeaderMeasurements {
diff --git a/src/types.ts b/src/types.ts
index 2bb38d4..00fbafc 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -135,8 +135,9 @@ export type CollapsibleProps = {
}
export type ContextType = {
- headerHeight: SharedValue
- tabBarHeight: SharedValue
+ headerHeight: number
+ tabBarHeight: number
+ containerHeight: number
revealHeaderOnScroll: boolean
snapThreshold: number | null | undefined
/**
@@ -169,7 +170,6 @@ export type ContextType = {
* Array of the scroll y position of each tab.
*/
scrollY: SharedValue>
- containerHeight: SharedValue
/**
* Object containing the ref of each scrollable component.
*/
@@ -209,7 +209,7 @@ export type ContextType = {
*/
contentHeights: SharedValue
- contentInset: SharedValue
+ contentInset: number
headerTranslateY: SharedValue