t1k:rn:performance:animations
| Field | Value |
|---|---|
| Module | performance |
| Version | 1.6.3 |
| Effort | medium |
| Tools | — |
Keywords: animations, gesture handler, layout animations, react native, reanimated, shared transitions
How to invoke
Section titled “How to invoke”/t1k:rn:performance:animationsRN Performance Animations
Section titled “RN Performance Animations”Reanimated 3 — Worklet Pattern
Section titled “Reanimated 3 — Worklet Pattern”import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, runOnJS, useAnimatedGestureHandler,} from 'react-native-reanimated';
// All worklet code runs on UI thread — never access JS state directlyfunction PressableCard() { const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], }));
return ( <Pressable onPressIn={() => { scale.value = withSpring(0.95); }} onPressOut={() => { scale.value = withSpring(1); }} > <Animated.View style={[styles.card, animatedStyle]} /> </Pressable> );}Gesture Handler
Section titled “Gesture Handler”import { GestureDetector, Gesture } from 'react-native-gesture-handler';
const pan = Gesture.Pan() .onUpdate((e) => { translateX.value = e.translationX; translateY.value = e.translationY; }) .onEnd(() => { translateX.value = withSpring(0); translateY.value = withSpring(0); });
return <GestureDetector gesture={pan}><Animated.View style={animStyle} /></GestureDetector>;Shared Element Transitions (Expo Router)
Section titled “Shared Element Transitions (Expo Router)”// Shared transition between screensimport { SharedTransition, withSpring } from 'react-native-reanimated';
const transition = SharedTransition.custom((values) => ({ width: withSpring(values.targetWidth), height: withSpring(values.targetHeight),}));
// Screen A<Animated.Image sharedTransitionTag="hero-image" sharedTransitionStyle={transition} />// Screen B<Animated.Image sharedTransitionTag="hero-image" sharedTransitionStyle={transition} />Layout Animations
Section titled “Layout Animations”import { FadeIn, FadeOut, SlideInRight, Layout } from 'react-native-reanimated';
<Animated.View entering={FadeIn.duration(300)} exiting={FadeOut} layout={Layout.springify()}> <Text>Animated content</Text></Animated.View>Key Rules
Section titled “Key Rules”- Worklets run on UI thread — never call JS functions directly, use
runOnJS() useSharedValuefor animated values — neveruseStatefor animation state- Wrap root in
<GestureHandlerRootView style={{ flex: 1 }}>— required for Gesture Handler - Use
withSpringfor natural feel,withTimingfor precise duration control
Gotchas
Section titled “Gotchas”'worklet'directive required for custom worklet functions called from animated styles- Shared transitions require both screens to use same
sharedTransitionTag GestureHandlerRootViewmust be outermost — beforeSafeAreaProviderand navigation- Layout animations on Android require
enableExperimentalLayoutAnimation()in older RN versions