--- title: Never Track Scroll Position in useState impact: HIGH impactDescription: prevents render thrashing during scroll tags: scroll, performance, reanimated, useRef --- ## Never Track Scroll Position in useState Never store scroll position in `useState`. Scroll events fire rapidly—state updates cause render thrashing and dropped frames. Use a Reanimated shared value for animations or a ref for non-reactive tracking. **Incorrect (useState causes jank):** ```tsx import { useState } from "react"; import { ScrollView, NativeSyntheticEvent, NativeScrollEvent } from "react-native"; function Feed() { const [scrollY, setScrollY] = useState(0); const onScroll = (e: NativeSyntheticEvent) => { setScrollY(e.nativeEvent.contentOffset.y); // re-renders on every frame }; return ; } ``` **Correct (Reanimated for animations):** ```tsx import Animated, { useSharedValue, useAnimatedScrollHandler } from "react-native-reanimated"; function Feed() { const scrollY = useSharedValue(0); const onScroll = useAnimatedScrollHandler({ onScroll: (e) => { scrollY.value = e.contentOffset.y; // runs on UI thread, no re-render }, }); return ( ); } ``` **Correct (ref for non-reactive tracking):** ```tsx import { useRef } from "react"; import { ScrollView, NativeSyntheticEvent, NativeScrollEvent } from "react-native"; function Feed() { const scrollY = useRef(0); const onScroll = (e: NativeSyntheticEvent) => { scrollY.current = e.nativeEvent.contentOffset.y; // no re-render }; return ; } ```