React Native Gestures: Building Smooth Interactions
Static mobile apps feel boring. Users expect to swipe, drag, and pinch. To achieve 60fps animations that respond to touch, we combine React Native Gesture Handler with Reanimated.
The Problem I Faced
I tried building a "swipe to delete" feature using the built-in React Native PanResponder. It was janky, blocked the JS thread, and stuttered on older Android devices. I needed a solution that ran on the UI thread.
Understanding Reanimated Worklets
Reanimated allows us to declare animation logic that runs entirely on the native UI thread, bypassing the React Native Javascript bridge bottleneck.
Code Example: Draggable Card
tsx
import React from 'react';
import { StyleSheet } from 'react-native';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
export default function DraggableCard() {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const gesture = Gesture.Pan()
.onUpdate((event) => {
translateX.value = event.translationX;
translateY.value = event.translationY;
})
.onEnd(() => {
// Snap back to center
translateX.value = withSpring(0);
translateY.value = withSpring(0);
});
const rStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
],
};
});
return (
<GestureDetector gesture={gesture}>
<Animated.View style={[styles.box, rStyle]} />
</GestureDetector>
);
}
const styles = StyleSheet.create({
box: { height: 100, width: 100, backgroundColor: '#E63946', borderRadius: 20 },
});Common Pitfalls
- Mistake 1: Forgetting
GestureHandlerRootView.- Don't: Wrap your component without the root provider.
- Do: Add
GestureHandlerRootViewat the very top of your App entry point (orapp/_layout.tsxin Expo Router).
Pro Tips
- Spring vs Timing: Use
withSpringfor natural, physics-based interaction. UsewithTimingfor linear, predictable movement. - Context: Use
useSharedValueto persist state between gesture events (like preserving the offset after a drag).
Wrapping Up
Fluid gestures make your app feel native and high-quality. With the declarative API of Gesture Handler 2.0, it's easier than ever.
Tech Stack: React Native, Expo, Reanimated, Gesture Handler
