react-draggable vs react-dnd vs react-beautiful-dnd vs react-grid-layout vs react-sortable-hoc vs react-movable
React Drag-and-Drop Libraries Comparison
1 Year
react-draggablereact-dndreact-beautiful-dndreact-grid-layoutreact-sortable-hocreact-movableSimilar Packages:
What's React Drag-and-Drop Libraries?

These libraries provide various functionalities for implementing drag-and-drop features in React applications. They cater to different use cases, from simple draggable components to complex grid layouts, allowing developers to enhance user experience through intuitive interactions. Each library has its unique strengths, making them suitable for different scenarios in web development. However, please note that react-beautiful-dnd has been deprecated and is no longer actively maintained, so it is recommended to consider alternative solutions like react-dnd or react-sortable-hoc for new projects.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-draggable3,634,9839,183244 kB2472 years agoMIT
react-dnd2,705,72621,465231 kB467-MIT
react-beautiful-dnd1,930,59833,9501.39 MB646-Apache-2.0
react-grid-layout871,83821,283527 kB2453 months agoMIT
react-sortable-hoc567,58010,882-2914 years agoMIT
react-movable53,9511,63750.7 kB114 months agoMIT
Feature Comparison: react-draggable vs react-dnd vs react-beautiful-dnd vs react-grid-layout vs react-sortable-hoc vs react-movable

Flexibility

  • react-draggable:

    react-draggable is highly flexible for making components draggable, but it lacks built-in support for drop targets or complex interactions, making it best for simple use cases.

  • react-dnd:

    react-dnd provides extensive flexibility, allowing developers to create complex drag-and-drop interactions with custom behaviors, making it suitable for advanced applications.

  • react-beautiful-dnd:

    react-beautiful-dnd offers a straightforward API for handling simple drag-and-drop interactions, but it may not support highly customized use cases without additional work. Due to its deprecation, it is recommended to explore other libraries for more flexibility.

  • react-grid-layout:

    react-grid-layout is flexible in creating grid layouts, allowing for draggable and resizable components, but it is more opinionated in structure compared to others.

  • react-sortable-hoc:

    react-sortable-hoc provides a flexible approach to creating sortable lists, allowing for easy integration and customization.

  • react-movable:

    react-movable is designed for simplicity and flexibility in moving list items, making it easy to implement without much overhead.

Performance

  • react-draggable:

    react-draggable is lightweight and performs well for simple draggable components, ensuring minimal impact on application performance.

  • react-dnd:

    react-dnd is performant but may require careful management of state and props to avoid unnecessary re-renders, especially in complex applications.

  • react-beautiful-dnd:

    react-beautiful-dnd is optimized for performance with smooth animations and minimal re-renders, ensuring a responsive user experience during drag-and-drop actions. However, since it is deprecated, it is advisable to explore alternatives for more consistent performance in the future.

  • react-grid-layout:

    react-grid-layout is designed for performance in grid layouts, but complex layouts with many items may require optimization to maintain responsiveness.

  • react-sortable-hoc:

    react-sortable-hoc is efficient for sortable lists, but performance may vary based on the complexity of the list and the number of items.

  • react-movable:

    react-movable is optimized for performance with minimal overhead, ensuring smooth interactions when moving items in a list.

Ease of Use

  • react-draggable:

    react-draggable is very easy to use, allowing developers to quickly make components draggable with minimal configuration.

  • react-dnd:

    react-dnd has a steeper learning curve due to its flexibility and customizability, requiring more understanding of its concepts and API.

  • react-beautiful-dnd:

    react-beautiful-dnd is user-friendly with a simple API, making it easy for developers to implement drag-and-drop functionality with minimal setup. However, given its deprecation, developers should consider the learning curve and community support of alternative libraries.

  • react-grid-layout:

    react-grid-layout is straightforward for creating grid layouts but may require additional learning for advanced features like resizing and responsive design.

  • react-sortable-hoc:

    react-sortable-hoc is relatively easy to use, allowing developers to create sortable lists with less boilerplate code.

  • react-movable:

    react-movable is designed for ease of use, providing a simple API for moving items in a list without complex configurations.

Community and Support

  • react-draggable:

    react-draggable has a smaller community but is well-documented, providing sufficient resources for basic implementations.

  • react-dnd:

    react-dnd has a large community and extensive documentation, making it easier to find solutions and examples for complex use cases.

  • react-beautiful-dnd:

    react-beautiful-dnd has a strong community and good documentation, providing ample resources for developers to get help and examples. However, since the library is deprecated, there will be limited updates or fixes going forward.

  • react-grid-layout:

    react-grid-layout has a dedicated community and good documentation, helping developers with grid-specific challenges and use cases.

  • react-sortable-hoc:

    react-sortable-hoc is well-supported with good documentation and examples, making it easy for developers to implement sortable lists.

  • react-movable:

    react-movable has a smaller user base but offers decent documentation, making it suitable for straightforward use cases.

Accessibility

  • react-draggable:

    react-draggable does not focus heavily on accessibility, so developers should implement their own solutions for keyboard navigation and screen readers.

  • react-dnd:

    react-dnd provides basic accessibility features, but developers may need to implement additional support for comprehensive accessibility.

  • react-beautiful-dnd:

    react-beautiful-dnd emphasizes accessibility, providing features that ensure drag-and-drop interactions are usable by all users, including keyboard navigation. However, developers should be aware that this library is no longer maintained, and exploring alternatives with active accessibility support is advisable.

  • react-grid-layout:

    react-grid-layout includes some accessibility features but may require additional work to ensure full compliance with accessibility standards.

  • react-sortable-hoc:

    react-sortable-hoc provides basic accessibility support, but developers should enhance it to meet specific accessibility requirements.

  • react-movable:

    react-movable does not have built-in accessibility features, requiring developers to handle accessibility considerations manually.

How to Choose: react-draggable vs react-dnd vs react-beautiful-dnd vs react-grid-layout vs react-sortable-hoc vs react-movable
  • react-draggable:

    Use react-draggable when you need to make individual components draggable without the overhead of a full drag-and-drop library. It is perfect for simple use cases where you want to allow users to move elements around the screen without complex interactions.

  • react-dnd:

    Select react-dnd for a more flexible and powerful drag-and-drop solution that supports complex interactions. It is ideal for applications that require custom drag-and-drop behavior, such as dragging items between different containers or implementing advanced features like drag previews and drop targets.

  • react-beautiful-dnd:

    Although react-beautiful-dnd was once a popular choice for creating simple and elegant drag-and-drop lists, it has been deprecated and is no longer actively maintained. For new projects, it is recommended to explore alternatives like react-dnd or react-sortable-hoc, which offer similar functionality and continued support.

  • react-grid-layout:

    Opt for react-grid-layout if you are building a responsive grid layout that allows users to drag and resize items. This library is excellent for dashboard-like interfaces where you want to provide a customizable layout for users.

  • react-sortable-hoc:

    Select react-sortable-hoc when you need to implement sortable lists with a higher-level abstraction. It is useful for scenarios where you want to create sortable lists or grids with minimal boilerplate code.

  • react-movable:

    Choose react-movable for a lightweight and simple solution to create movable lists. It is great for scenarios where you want to reorder items in a list with minimal setup and a focus on performance.

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