PanResponder: The Gesture State Machine
PanResponder turns raw touch events into a single, stateful gesture, like dragging an object. It's used to build draggable elements by providing a `gestureState` object with velocity and distance. The footgun is confusing `moveX/Y` with `dx/dy`.
WHY IT EXISTS The raw touch system in mobile OSes is low-level. Building a simple "drag" requires tracking start points, current points, and deciding which component "owns" the touch. PanResponder was created to abstract this complex state management into a predictable wrapper.
THE MENTAL MODEL Think of PanResponder as a gesture negotiator and state tracker. It asks, "Should I handle this touch?" If it wins the negotiation, it starts tracking the gesture and provides a rich gestureState object with all the info you need, like how far the finger has moved (dx, dy) and how fast (vx, vy).
HOW IT WORKS You create a PanResponder using PanResponder.create(), passing a configuration object of callbacks that define the gesture's lifecycle. First, you use onStartShouldSetPanResponder or onMoveShouldSetPanResponder to "claim" a gesture by returning true. Once granted (onPanResponderGrant), you can react to movement with onPanResponderMove. The gestureState object passed to these callbacks contains derived values like dx, dy (accumulated distance), and numberActiveTouches. You apply these handlers to a View using the {...panResponder.panHandlers} spread prop.
WHEN TO USE IT Use PanResponder when you need to create custom gestures beyond a simple tap. It's ideal for dragging elements, basic pinching (by tracking numberActiveTouches), or any interaction where you need the gesture's velocity or total distance traveled. It is designed to work with the Animated API to translate gesture data into smooth UI animations.
WHEN NOT TO USE IT For simple presses or long presses, React Native's built-in Pressable or TouchableOpacity components are simpler. PanResponder is overkill for basic button-like behavior. Its power lies in handling continuous, stateful gestures, not discrete actions.
ONE CANONICAL EXAMPLE A draggable card. In onPanResponderMove, you use the gestureState.dx and gestureState.dy values to update the position of an Animated.View. When the user lets go (onPanResponderRelease), you can animate the card back to its origin. The dx and dy are perfect for this because they represent the total change from where the drag started, not the absolute screen coordinates.
Read the original → reactnative.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.