Back to Blogs

React Native Gestures: Building Smooth Interactions with Gesture HandlerReact Native Gestures: Building Smooth Interactions with Gesture Handler

10 months ago
React Native Gestures: Building Smooth Interactions with Gesture Handler

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 GestureHandlerRootView at the very top of your App entry point (or app/_layout.tsx in Expo Router).

Pro Tips

  1. Spring vs Timing: Use withSpring for natural, physics-based interaction. Use withTiming for linear, predictable movement.
  2. Context: Use useSharedValue to 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