Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 1,000,000+ packages pre-installed, including react-gesture-responder with all npm packages installed. Try it out:

require("react/package.json"); // react is a peer dependency. require("react-dom/package.json"); // react-dom is a peer dependency. var reactGestureResponder = require("react-gesture-responder")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

react-gesture-responder v2.1.0

A react-native like gesture helper for the React and using hooks

A demo showing a ball being pulled around, released, and animating back into place.


npm package Follow on Twitter

react-gesture-responder offers a gesture responder system for your react application. It's heavily inspired by react-native's pan-responder. It's built for use in Sancho-UI.


  • The ability to delegate between multiple overlapping gestures. This means that you can embed gesture responding views within eachother and provide negotiation strategies between them.
  • Simple kinematics for gesture based animations. Values including distance, velocity, delta, and direction are provided through gesture callbacks.
  • Integrates well with react-spring to create performant animations.
  • Built with react-gesture-responder: react-gesture-view, touchable-hook, sancho-ui.

Getting started

Install into your react project using yarn or npm.

yarn add react-gesture-responder

The example below demonstrates how it can be used in conjunction with react-spring.

import { useSpring, animated } from "react-spring";
import { useGestureResponder } from "react-gesture-responder";

function Draggable() {
  const [{ xy }, set] = useSpring(() => ({
    xy: [0, 0]

  const { bind } = useGestureResponder({
    onStartShouldSet: () => true,
    onRelease: onEnd,
    onTerminate: onEnd,
    onMove: ({ delta }) => {
        xy: delta,
        immediate: true

  function onEnd() {
    set({ xy: [0, 0], immediate: false });

  return (
        transform: xy.interpolate((x, y) => `translate3d(${x}px, ${y}px, 0)`)


Only one responder can be active at any given time. The useGesture hook provides callbacks which allow you to implement a negotiation strategy between competing views.

  • onStartShouldSet: (state, e) => boolean - Should the view become the responder upon first touch?
  • onMoveShouldSet: (state, e) => boolean - This is called during any gesture movement on the view. You can return true to claim the responder for that view.
  • onStartShouldSetCapture: (state, e) => boolean - The same as above, but using event capturing instead of bubbling. Useful if you want a parent view to capture the responder prior to children.
  • onMoveShouldSetCapture: (state, e) => boolean.
  • onTerminationRequest: (state) => boolean. - Should we allow the responder to be claimed by another view? This is only called when a parent onMoveShouldSet returns true. By default, it returns true.

By default, if a parent and child both return true from onStartShouldSet the child element will claim the responder.

Once a responder is claimed, other callbacks can be used to provide visual feedback to the user.

  • onGrant: (state, e) => void - called when the view claims the responder, typically corresponding with mousedown or touchstart events.
  • onMove: (state, e) => void
  • onRelease: (state, e) => void - corresponds with mouseup or touchend events.
  • onTerminate: (state) => void - called when the responder is claimed by another view.
const { bind } = useGestureResponder(
    onStartShouldSet: state => true,
    onStartShouldSetCapture: state => false,
    onMoveShouldSet: state => false,
    onMoveShouldSetCapture: state => false,
    onTerminationRequest: state => true,
    onGrant: state => {},
    onRelease: state => {},
    onTerminate: state => {},
    onMove: state => {}
    uid: "a-unique-id",
    enableMouse: true

state contains the following values:

export interface StateType {
  time: number;
  xy: [number, number];
  delta: [number, number];
  initial: [number, number];
  previous: [number, number];
  direction: [number, number];
  initialDirection: [number, number];
  local: [number, number];
  lastLocal: [number, number];
  velocity: number;
  distance: number;

Prior art

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free