Performance
Use the native driver
Springs and fades in the kit use Animated with useNativeDriver: true for transform and opacity. That keeps animation off the JavaScript thread while React is busy.
import { Animated } from "react-native";import { motion } from "@/lib/kit"; Animated.spring(scale, { toValue: pressed ? 0.96 : 1, useNativeDriver: true, ...motion.bouncy,}).start();width, height or margin every frame — they force layout. Prefer transform and opacity, or a one-time layout measure then animate scale.Do not setState every frame
Driving UI from scroll or drag with setState re-renders the whole subtree on every event. Keep the animated value in Animated.Value (or Reanimated shared values if you adopt them). Only commit to React state when the gesture ends or when a human-readable label must change.
Lists
Long settings screens should use FlatList or FlashList, not a ScrollView of hundreds of rows. Memoize row components and stabilise renderItem with useCallback.
Measure in release
Debug builds are slower. Profile jank on a real device in release before ripping out animations:
npx expo run:ios --device --configuration Release# ornpx expo run:android --variant releaseReduced motion
Where the kit loops (skeleton shimmer, loading pulses), respect the system accessibility setting when you add your own loops — static fallbacks are both correct and cheaper.