--- 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 } ```