useScrollToTop
Pre-alphaThe registry and the CLI are not published yet.Roadmap

useScrollToTop

Show a scroll-to-top button past a threshold and bring a list back to its top.

Draft

The API shown here is conceptual and may change.

The hook behind Scroll-to-top. That page explains when the button shows, the jump before the animation, the other triggers and accessibility. This one covers the API.

Installation

npx axiom add use-scroll-to-top
pnpm dlx axiom add use-scroll-to-top
yarn dlx axiom add use-scroll-to-top
bun x axiom add use-scroll-to-top

Installs: react-native-reanimated.

Usage

Conceptual
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
import { useScrollToTop } from "@/hooks/use-scroll-to-top";

function News() {
	const top = useScrollToTop({ showOn: "scroll-up" });

	return (
		<View style={{ flex: 1 }}>
			<Animated.FlatList
				data={articles}
				renderItem={renderArticle}
				{...top.scrollProps}
			/>
			{top.visible && (
				<Animated.View
					entering={FadeIn}
					exiting={FadeOut}
					style={styles.fab}
				>
					<IconButton
						icon="arrow-up"
						variant="solid"
						accessibilityLabel="Scroll to top"
						onPress={top.scrollToTop}
					/>
				</Animated.View>
			)}
		</View>
	);
}

visible is React state. It changes when the offset crosses threshold or the scroll direction flips, not on every frame.

With your own list ref

scrollProps includes a ref. If you already hold one, pass it in and the hook uses it:

Conceptual
const listRef = useAnimatedRef<FlatList<Article>>();
const top = useScrollToTop({ ref: listRef });

<Animated.FlatList ref={listRef} onScroll={top.scrollProps.onScroll}  />

Without a button

On a short list, skip the button and keep the tab press and the status bar tap:

Conceptual
const top = useScrollToTop({ threshold: Infinity });

Moving focus after the return

onTop is called once the list reaches 0 after scrollToTop(). Use it to move screen reader focus:

Conceptual
useScrollToTop({
	onTop: () =>
		AccessibilityInfo.setAccessibilityFocus(
			findNodeHandle(titleRef.current)!,
		),
});

Options

OptionTypeDefaultDescription
thresholdnumberlist heightOffset in pt past which the button can show. Infinity never shows it.
showOn'always' | 'scroll-up''always'always shows it past the threshold. scroll-up only while the user scrolls up.
jumpDistancenumber2 × thresholdPast this offset, the list jumps to threshold before animating.
tabPressbooleantrueScrolls to the top when the selected tab is pressed again. Requires React Navigation.
refAnimatedRefYour own list ref. Created for you otherwise.
onTop() => voidCalled when a scrollToTop() reaches 0.

Return value

KeyTypeDescription
visiblebooleanWhether to show the button. React state.
offsetSharedValue<number>Current scroll offset, for a button that animates with the scroll.
scrollToTop() => voidJumps if needed, then animates to 0. Instant with Reduce Motion.
scrollPropsobjectref, onScroll, scrollEventThrottle and scrollsToTop, for an Animated ScrollView, FlatList, SectionList or FlashList.