react-draggable vs react-dnd vs @use-gesture/react vs react-spring vs react-use-gesture vs react-move
React Gesture and Drag Libraries Comparison
1 Year
react-draggablereact-dnd@use-gesture/reactreact-springreact-use-gesturereact-moveSimilar Packages:
What's React Gesture and Drag Libraries?

These libraries provide various functionalities for handling gestures and drag-and-drop interactions in React applications. They enable developers to create interactive and dynamic user interfaces by simplifying the implementation of touch and mouse events, enhancing user experience through smooth animations and intuitive controls. Each library has its unique approach and features tailored for different use cases, from simple draggable elements to complex gesture recognition.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-draggable2,954,8229,174244 kB2472 years agoMIT
react-dnd2,603,95521,427231 kB466-MIT
@use-gesture/react951,5369,35637.2 kB44a year agoMIT
react-spring826,75828,7008.36 kB1184 days agoMIT
react-use-gesture247,5309,356-444 years agoMIT
react-move68,5046,587-284 years agoMIT
Feature Comparison: react-draggable vs react-dnd vs @use-gesture/react vs react-spring vs react-use-gesture vs react-move

Gesture Recognition

  • react-draggable:

    react-draggable offers basic drag functionality, allowing elements to be moved with mouse or touch events. It does not support advanced gestures like pinch or swipe, making it suitable for simple draggable elements.

  • react-dnd:

    react-dnd focuses on drag-and-drop interactions rather than gesture recognition. While it supports mouse and touch events, its primary purpose is to manage the state and behavior of draggable components within a defined drop zone.

  • @use-gesture/react:

    @use-gesture/react provides a straightforward API for recognizing various gestures including drag, pinch, and swipe. It allows developers to easily implement complex gesture interactions with minimal boilerplate code, making it ideal for touch-based applications.

  • react-spring:

    react-spring excels in creating fluid animations and can handle drag interactions through its animation capabilities. It allows for gesture-based animations but requires additional setup for gesture recognition.

  • react-use-gesture:

    react-use-gesture is designed for comprehensive gesture recognition, allowing developers to define custom gestures and handle them efficiently. It supports a wide range of gestures and is highly customizable.

  • react-move:

    react-move is primarily an animation library that enhances drag interactions with smooth transitions. It does not focus on gesture recognition but rather on animating elements during drag events, providing visual feedback to users.

Ease of Use

  • react-draggable:

    react-draggable is very user-friendly, allowing developers to quickly make components draggable with minimal configuration. It is straightforward and ideal for simple use cases.

  • react-dnd:

    react-dnd has a steeper learning curve due to its complex API and the need to understand the concepts of drag sources and drop targets. It is powerful but may require more time to implement effectively.

  • @use-gesture/react:

    @use-gesture/react is easy to use with a simple API that integrates well with React. It requires minimal setup and is great for developers looking to add gesture support without a steep learning curve.

  • react-spring:

    react-spring has a moderate learning curve, especially for developers unfamiliar with physics-based animations. However, once understood, it provides powerful tools for creating complex animations.

  • react-use-gesture:

    react-use-gesture is designed to be intuitive and easy to use, providing a clear API for handling gestures. It is suitable for both beginners and experienced developers.

  • react-move:

    react-move is easy to integrate for animating drag interactions, but it may require some understanding of animation principles to fully utilize its capabilities.

Animation Support

  • react-draggable:

    react-draggable offers basic drag functionality but does not include advanced animation capabilities. Developers can add animations manually if desired, but it is not inherently supported.

  • react-dnd:

    react-dnd does not focus on animations; it primarily manages the drag-and-drop logic. Developers can implement animations separately if needed, but it is not a core feature of the library.

  • @use-gesture/react:

    @use-gesture/react does not provide built-in animation support, focusing solely on gesture recognition. Developers need to integrate it with animation libraries for visual feedback during gestures.

  • react-spring:

    react-spring is a powerful animation library that can create complex animations and transitions, including during drag interactions. It offers a physics-based approach, making animations feel more natural and fluid.

  • react-use-gesture:

    react-use-gesture does not provide animation support out of the box, but it can be easily combined with animation libraries like react-spring to create dynamic and responsive gesture-based animations.

  • react-move:

    react-move is specifically designed for animations, providing smooth transitions during drag events. It excels at enhancing the visual experience of dragging elements.

Performance

  • react-draggable:

    react-draggable is lightweight and performs well for simple draggable elements. It is efficient for basic use cases but may not scale well for complex interactions involving many draggable items.

  • react-dnd:

    react-dnd can introduce performance overhead due to its complex state management for drag-and-drop interactions. However, it is designed to handle large lists and complex interactions efficiently when implemented correctly.

  • @use-gesture/react:

    @use-gesture/react is optimized for performance, allowing for efficient gesture handling without significant overhead. It is suitable for applications that require high responsiveness during user interactions.

  • react-spring:

    react-spring is built for performance, using a physics-based approach to animations that can handle complex interactions without sacrificing responsiveness. It is suitable for applications that require fluid animations.

  • react-use-gesture:

    react-use-gesture is designed with performance in mind, allowing for efficient gesture recognition and handling. It minimizes re-renders and optimizes performance during user interactions.

  • react-move:

    react-move is optimized for animations, ensuring smooth transitions during drag events. It is designed to minimize performance impact while providing visually appealing animations.

Use Cases

  • react-draggable:

    react-draggable is perfect for simple use cases where you need to make elements draggable, such as draggable modals, sliders, or simple interactive interfaces.

  • react-dnd:

    react-dnd is best suited for applications that require complex drag-and-drop functionality, such as kanban boards, file upload interfaces, or any scenario where users need to rearrange items.

  • @use-gesture/react:

    @use-gesture/react is ideal for applications that require touch and gesture support, such as mobile apps or interactive web applications where gestures enhance user experience.

  • react-spring:

    react-spring is suitable for applications that require advanced animations and transitions, including drag interactions, making it ideal for creative and visually rich interfaces.

  • react-use-gesture:

    react-use-gesture is versatile and can be used in various applications requiring gesture recognition, such as games, touch interfaces, or any interactive application that benefits from custom gesture handling.

  • react-move:

    react-move is great for applications that require smooth animations during drag events, enhancing the visual experience of dragging elements across the screen.

How to Choose: react-draggable vs react-dnd vs @use-gesture/react vs react-spring vs react-use-gesture vs react-move
  • react-draggable:

    Select react-draggable for straightforward draggable components that require minimal configuration. It's ideal for simple use cases where you need to make elements draggable without the overhead of a full drag-and-drop library.

  • react-dnd:

    Opt for react-dnd if you require a robust drag-and-drop interface with support for complex interactions, such as nested drag sources and drop targets, and if you need to manage state and data transfer during drag-and-drop operations.

  • @use-gesture/react:

    Choose @use-gesture/react if you need a lightweight solution focused on gesture recognition, including pinch, swipe, and drag events, with a simple API for handling complex gestures in your React components.

  • react-spring:

    Choose react-spring if you are looking for a powerful animation library that can handle complex animations and transitions, including drag interactions. It offers a physics-based approach to animations, allowing for more natural movement effects.

  • react-use-gesture:

    Select react-use-gesture if you want a flexible and customizable library for handling gestures with a focus on performance and simplicity. It allows you to create custom gesture handlers and is suitable for applications that require fine-tuned gesture recognition.

  • react-move:

    Use react-move when you want to create smooth animations and transitions during drag events. It provides a simple API for animating elements based on their position, making it suitable for visually appealing interfaces.

README for react-draggable

React-Draggable

TravisCI Build Status Appveyor Build Status npm downloads gzip size version

A simple component for making elements draggable.

<Draggable>
  <div>I can now be moved around!</div>
</Draggable>

|Version | Compatibility| |------------|--------------| |4.x | React 16.3+ | |3.x | React 15-16 | |2.x | React 0.14 - 15 | |1.x | React 0.13 - 0.14 | |0.x | React 0.10 - 0.13 |


Technical Documentation

Installing

$ npm install react-draggable

If you aren't using browserify/webpack, a UMD version of react-draggable is available. It is updated per-release only. This bundle is also what is loaded when installing from npm. It expects external React and ReactDOM.

If you want a UMD version of the latest master revision, you can generate it yourself from master by cloning this repository and running $ make. This will create umd dist files in the dist/ folder.

Exports

The default export is <Draggable>. At the .DraggableCore property is <DraggableCore>. Here's how to use it:

// ES6
import Draggable from 'react-draggable'; // The default
import {DraggableCore} from 'react-draggable'; // <DraggableCore>
import Draggable, {DraggableCore} from 'react-draggable'; // Both at the same time

// CommonJS
let Draggable = require('react-draggable');
let DraggableCore = Draggable.DraggableCore;

<Draggable>

A <Draggable> element wraps an existing element and extends it with new event handlers and styles. It does not create a wrapper element in the DOM.

Draggable items are moved using CSS Transforms. This allows items to be dragged regardless of their current positioning (relative, absolute, or static). Elements can also be moved between drags without incident.

If the item you are dragging already has a CSS Transform applied, it will be overwritten by <Draggable>. Use an intermediate wrapper (<Draggable><span>...</span></Draggable>) in this case.

Draggable Usage

View the Demo and its source for more.

import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';

class App extends React.Component {

  eventLogger = (e: MouseEvent, data: Object) => {
    console.log('Event: ', e);
    console.log('Data: ', data);
  };

  render() {
    return (
      <Draggable
        axis="x"
        handle=".handle"
        defaultPosition={{x: 0, y: 0}}
        position={null}
        grid={[25, 25]}
        scale={1}
        onStart={this.handleStart}
        onDrag={this.handleDrag}
        onStop={this.handleStop}>
        <div>
          <div className="handle">Drag from here</div>
          <div>This readme is really dragging on...</div>
        </div>
      </Draggable>
    );
  }
}

ReactDOM.render(<App/>, document.body);

Draggable API

The <Draggable/> component transparently adds draggability to its children.

Note: Only a single child is allowed or an Error will be thrown.

For the <Draggable/> component to correctly attach itself to its child, the child element must provide support for the following props:

  • style is used to give the transform css to the child.
  • className is used to apply the proper classes to the object being dragged.
  • onMouseDown, onMouseUp, onTouchStart, and onTouchEnd are used to keep track of dragging state.

React.DOM elements support the above properties by default, so you may use those elements as children without any changes. If you wish to use a React component you created, you'll need to be sure to transfer prop.

<Draggable> Props:

//
// Types:
//
type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
type DraggableData = {
  node: HTMLElement,
  // lastX + deltaX === x
  x: number, y: number,
  deltaX: number, deltaY: number,
  lastX: number, lastY: number
};

//
// Props:
//
{
// If set to `true`, will allow dragging on non left-button clicks.
allowAnyClick: boolean,

// Determines which axis the draggable can move. This only affects
// flushing to the DOM. Callbacks will still include all values.
// Accepted values:
// - `both` allows movement horizontally and vertically (default).
// - `x` limits movement to horizontal axis.
// - `y` limits movement to vertical axis.
// - 'none' stops all movement.
axis: string,

// Specifies movement boundaries. Accepted values:
// - `parent` restricts movement within the node's offsetParent
//    (nearest node with position relative or absolute), or
// - a selector, restricts movement within the targeted node
// - An object with `left, top, right, and bottom` properties.
//   These indicate how far in each direction the draggable
//   can be moved.
bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

// Specifies a selector to be used to prevent drag initialization. The string is passed to
// Element.matches, so it's possible to use multiple selectors like `.first, .second`.
// Example: '.body'
cancel: string,

// Class names for draggable UI.
// Default to 'react-draggable', 'react-draggable-dragging', and 'react-draggable-dragged'
defaultClassName: string,
defaultClassNameDragging: string,
defaultClassNameDragged: string,

// Specifies the `x` and `y` that the dragged item should start at.
// This is generally not necessary to use (you can use absolute or relative
// positioning of the child directly), but can be helpful for uniformity in
// your callbacks and with css transforms.
defaultPosition: {x: number, y: number},

// If true, will not call any drag handlers.
disabled: boolean,

// Specifies the x and y that dragging should snap to.
grid: [number, number],

// Specifies a selector to be used as the handle that initiates drag.
// Example: '.handle'
handle: string,

// If desired, you can provide your own offsetParent for drag calculations.
// By default, we use the Draggable's offsetParent. This can be useful for elements
// with odd display types or floats.
offsetParent: HTMLElement,

// Called whenever the user mouses down. Called regardless of handle or
// disabled status.
onMouseDown: (e: MouseEvent) => void,

// Called when dragging starts. If `false` is returned any handler,
// the action will cancel.
onStart: DraggableEventHandler,

// Called while dragging.
onDrag: DraggableEventHandler,

// Called when dragging stops.
onStop: DraggableEventHandler,

// If running in React Strict mode, ReactDOM.findDOMNode() is deprecated.
// Unfortunately, in order for <Draggable> to work properly, we need raw access
// to the underlying DOM node. If you want to avoid the warning, pass a `nodeRef`
// as in this example:
//
// function MyComponent() {
//   const nodeRef = React.useRef(null);
//   return (
//     <Draggable nodeRef={nodeRef}>
//       <div ref={nodeRef}>Example Target</div>
//     </Draggable>
//   );
// }
//
// This can be used for arbitrarily nested components, so long as the ref ends up
// pointing to the actual child DOM node and not a custom component.
//
// For rich components, you need to both forward the ref *and props* to the underlying DOM
// element. Props must be forwarded so that DOM event handlers can be attached. 
// For example:
//
//   const Component1 = React.forwardRef(function (props, ref) {
//     return <div {...props} ref={ref}>Nested component</div>;
//   });
//
//   const nodeRef = React.useRef(null);
//   <DraggableCore onDrag={onDrag} nodeRef={nodeRef}>
//     <Component1 ref={nodeRef} />
//   </DraggableCore>
//
// Thanks to react-transition-group for the inspiration.
//
// `nodeRef` is also available on <DraggableCore>.
nodeRef: React.Ref<typeof React.Component>,

// Much like React form elements, if this property is present, the item
// becomes 'controlled' and is not responsive to user input. Use `position`
// if you need to have direct control of the element.
position: {x: number, y: number}

// A position offset to start with. Useful for giving an initial position
// to the element. Differs from `defaultPosition` in that it does not
// affect the position returned in draggable callbacks, and in that it
// accepts strings, like `{x: '10%', y: '10%'}`.
positionOffset: {x: number | string, y: number | string},

// Specifies the scale of the canvas your are dragging this element on. This allows
// you to, for example, get the correct drag deltas while you are zoomed in or out via
// a transform or matrix in the parent of this element.
scale: number
}

Note that sending className, style, or transform as properties will error - set them on the child element directly.

Controlled vs. Uncontrolled

<Draggable> is a 'batteries-included' component that manages its own state. If you want to completely control the lifecycle of the component, use <DraggableCore>.

For some users, they may want the nice state management that <Draggable> provides, but occasionally want to programmatically reposition their components. <Draggable> allows this customization via a system that is similar to how React handles form components.

If the prop position: {x: number, y: number} is defined, the <Draggable> will ignore its internal state and use the provided position instead. Alternatively, you can seed the position using defaultPosition. Technically, since <Draggable> works only on position deltas, you could also seed the initial position using CSS top/left.

We make one modification to the React philosophy here - we still allow dragging while a component is controlled. We then expect you to use at least an onDrag or onStop handler to synchronize state.

To disable dragging while controlled, send the prop disabled={true} - at this point the <Draggable> will operate like a completely static component.

<DraggableCore>

For users that require absolute control, a <DraggableCore> element is available. This is useful as an abstraction over touch and mouse events, but with full control. <DraggableCore> has no internal state.

See React-Resizable and React-Grid-Layout for some usage examples.

<DraggableCore> is a useful building block for other libraries that simply want to abstract browser-specific quirks and receive callbacks when a user attempts to move an element. It does not set styles or transforms on itself and thus must have callbacks attached to be useful.

DraggableCore API

<DraggableCore> takes a limited subset of options:

{
  allowAnyClick: boolean,
  cancel: string,
  disabled: boolean,
  enableUserSelectHack: boolean,
  offsetParent: HTMLElement,
  grid: [number, number],
  handle: string,
  onStart: DraggableEventHandler,
  onDrag: DraggableEventHandler,
  onStop: DraggableEventHandler,
  onMouseDown: (e: MouseEvent) => void,
  scale: number
}

Note that there is no start position. <DraggableCore> simply calls drag handlers with the below parameters, indicating its position (as inferred from the underlying MouseEvent) and deltas. It is up to the parent to set actual positions on <DraggableCore>.

Drag callbacks (onStart, onDrag, onStop) are called with the same arguments as <Draggable>.


Contributing

  • Fork the project
  • Run the project in development mode: $ npm run dev
  • Make changes.
  • Add appropriate tests
  • $ npm test
  • If tests don't pass, make them pass.
  • Update README with appropriate docs.
  • Commit and PR

Release checklist

  • Update CHANGELOG
  • make release-patch, make release-minor, or make-release-major
  • make publish

License

MIT