Building Native-Like Animations in React Native

A practical guide to smooth, 60fps animations in React Native using Reanimated, with working code.

Why the Default Animated API Falls Short

React Native’s built-in Animated API runs most animation logic on the JavaScript thread, which can drop frames under load. The react-native-reanimated library moves animation logic onto the UI thread, giving genuinely native-feeling performance.

Installing Reanimated

npm install react-native-reanimated

A Simple Fade and Scale Animation

import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

function LikeButton() {
  const scale = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: scale.value }],
  }));

  const handlePress = () => {
    scale.value = withSpring(1.3, {}, () => {
      scale.value = withSpring(1);
    });
  };

  return (
    <Animated.View style={animatedStyle}>
      <Pressable onPress={handlePress}>
        <Icon name="heart" size={32} />
      </Pressable>
    </Animated.View>
  );
}

Gesture-Driven Animations

import { Gesture, GestureDetector } from 'react-native-gesture-handler';

function SwipeableCard() {
  const translateX = useSharedValue(0);

  const gesture = Gesture.Pan()
    .onUpdate((e) => {
      translateX.value = e.translationX;
    })
    .onEnd(() => {
      translateX.value = withSpring(0);
    });

  const style = useAnimatedStyle(() => ({
    transform: [{ translateX: translateX.value }],
  }));

  return (
    <GestureDetector gesture={gesture}>
      <Animated.View style={[styles.card, style]} />
    </GestureDetector>
  );
}

Layout Animations

import Animated, { FadeIn, FadeOut, Layout } from 'react-native-reanimated';

<Animated.View entering={FadeIn} exiting={FadeOut} layout={Layout.springify()}>
  <ListItem />
</Animated.View>

Performance Tips

  • Keep animation logic in shared values and worklets, not React state, to avoid unnecessary re-renders.
  • Use withSpring and withTiming instead of manually stepping values on every frame.
  • Profile with the Flipper performance monitor to catch dropped frames before shipping.

Conclusion

Reanimated’s worklet-based approach is what makes genuinely smooth, native-feeling animations possible in React Native. Once you’re comfortable with shared values and the animated style pattern, most common animation needs — taps, swipes, transitions — become straightforward to implement.