react-draggable: a drag component that moves your element with CSS transforms
React draggable component
At a glance
- What is it?
- react-draggable wraps an existing element and moves it with CSS transforms rather than a wrapper div. It is a small, MIT-licensed component for React 16.3+, and the README leaves a few things, including rollback and upgrade paths, undocumented.
- Who is it for?
- Adopt react-draggable when you need one element or a short list of elements to follow the pointer and you are willing to manage layout yourself: the README shows the install command, the nodeRef pattern and the DraggableCore escape hatch, and that is the whole surface.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What react-draggable actually does that a pointer handler does not
The pitch in the README is one line of JSX: wrap a div in <Draggable> and it can be moved. The interesting part is what that wrapper does not do. According to the README, a <Draggable> element "does not create a wrapper element in the DOM"; it extends the child with event handlers and styles instead. That matters if your layout depends on parent-child selectors, flex ordering or grid placement, because an extra div in the tree would break all three.
Movement is applied through CSS transforms, which the README justifies by noting that items can then be dragged regardless of whether their current positioning is relative, absolute or static. A component that instead wrote left and top would fight any absolutely positioned parent and would recompute layout on every pointer move. Transforms keep the work on the compositor side in most browsers.
The cost of that choice is stated plainly: if the element you are dragging already carries a CSS transform, <Draggable> overwrites it. The README's suggested fix is an intermediate wrapper such as <Draggable><span>...</span></Draggable>. This is a real constraint, not a footnote. Any element already using transform for centering, scaling or an entrance animation is a candidate for silent breakage.
The audience is narrow and clear. If you are building a dashboard where panels move, a canvas-like editor, or a floating window, this is the primitive. If you want a sortable list with drop indicators and keyboard support, this is the wrong layer, and nothing in the README pretends otherwise.
Draggable versus DraggableCore: where the state lives
The package exports two components, and choosing between them is the first real decision. <Draggable> is described in the README as "batteries-included" and manages its own state, applying transforms and class names for you. <DraggableCore> provides drag callbacks "without managing state or styles" and sets no transforms at all, so you position the element yourself.
The callback signature is shared. A DraggableEventHandler receives the event and a DraggableData object carrying node, x, y, deltaX, deltaY, lastX and lastY. Returning false from onStart cancels the drag, which is how you implement a guard such as "do not move this panel while it is being edited".
DraggableCore accepts a subset of the Draggable props: allowAnyClick, allowMobileScroll, cancel, disabled, enableUserSelectHack, grid, handle, nodeRef, offsetParent, onDrag, onMouseDown, onStart, onStop and scale. Note what is absent. There is no position, no defaultPosition and no bounds, because bounds enforcement belongs to the stateful layer. If you need constrained movement with DraggableCore, you clamp the coordinates inside your own onDrag handler.
The README points at React-Resizable and React-Grid-Layout as usage examples of DraggableCore. That is the honest signal about who the core is for: library authors building a higher-level interaction, not application developers who just want a movable box.
Installing react-draggable and making a first element draggable
Installation is a single npm or yarn command, and the package ships TypeScript types, so no separate @types package is needed. The README gives both package managers and both module systems:
npm install react-draggableAfter install, the smallest working example needs a ref. The README's Quick Start uses nodeRef with useRef, and the Using nodeRef section states that this prop is required to avoid ReactDOM.findDOMNode() deprecation warnings in React Strict Mode. Skipping it is the most common way to get a console full of warnings on a modern React setup.
import React, { useRef } from 'react';
import Draggable from 'react-draggable';
function App() {
const nodeRef = useRef(null);
return (
<Draggable nodeRef={nodeRef}>
<div ref={nodeRef}>Drag me!</div>
</Draggable>
);
}The same ref goes on the Draggable prop and on the child element. If the child is a custom component, the README shows forwarding both ref and props with forwardRef, then passing ref={nodeRef} to that component. Once the element moves, the next step most people take is constraining it. The bounds prop accepts the string 'parent', a CSS selector, or an object with left, top, right and bottom. The grid prop takes a two-number array and snaps movement to that spacing. Both are documented in the props table, and both are absent from DraggableCore.
Where react-draggable breaks or is the wrong tool
The transform overwrite is the first failure mode, and it is silent. You wrap an element that is already translated for a tooltip offset or a slide-in animation, drag it once, and the original transform is gone. The README's wrapper suggestion works, but it changes your DOM, which is exactly what the no-wrapper design was avoiding. There is no prop to compose transforms.
The second is Strict Mode. Without nodeRef, the component falls back to a DOM lookup path that the README describes only in terms of deprecation warnings. The README does not describe what happens if nodeRef is passed to the Draggable but omitted on the child, so verify that pairing yourself rather than assuming a helpful error.
Touch behaviour is opt-in in a way that surprises people. allowMobileScroll defaults to false, which means touchstart is prevented by default. If you are dragging a panel that sits inside a scrollable container on a phone, the container will not scroll until you set allowMobileScroll. The README documents the prop and its default but does not walk through the interaction.
Finally, consider what is missing by design. There is no keyboard dragging, no ARIA role management and no drop-target model in the documented API. A drag-only interaction is inaccessible to keyboard users unless you build the alternative yourself. For a sortable list with announcements and focus management, this is the wrong dependency, and the README never claims otherwise.
react-draggable against dnd-kit and react-dnd
People search for react-draggable versus dnd kit and react draggable versus react dnd, and the difference is architectural rather than cosmetic. react-draggable answers one question: where is this element now. Its state is a pair of coordinates, its output is a CSS transform, and its API is a props table. There is no concept of a droppable region, no collision detection and no sortable ordering.
dnd-kit and react-dnd both model a drag as a transfer between a source and a target. They give you sensors, collision detection and, in dnd-kit's case, an accessibility layer with keyboard coordinates. That is a different amount of machinery, and it comes with a different amount of API surface to learn.
The practical split: if your panels are absolutely positioned and you only need to move them, react-draggable plus your own layout code is smaller than pulling in a full drag-and-drop framework. If items need to reorder, swap or land in containers, the coordinate model is the wrong abstraction and you will end up rebuilding collision logic on top of onDrag. Note also that the README points to React-Resizable for the resize half of the problem; that is a separate package, not a prop on Draggable, so a resizable-and-draggable panel means two dependencies and two refs on the same node.
Maintenance, versions and what the licence allows
The repository is not archived, and the last push was on 2026-09-16. The published version in package.json is 4.7.2, while the recent release list shows 2.2.3 from 2016-12-08; the version numbers in package.json and the release feed do not line up, so treat the npm version as the source of truth and read CHANGELOG.md before upgrading rather than trusting the release list.
The compatibility table maps major versions to React: 4.x needs React 16.3 or newer, 3.x covers React 15 through 16, and 2.x covers 0.14 through 15. That table is the upgrade contract. Moving a React 15 codebase to React 18 or 19 means moving to 4.x, and the nodeRef requirement is part of that move.
Build and release are Makefile-driven. The build target runs build-lib and build-web, then node scripts/verify-build.cjs, which the Makefile comment says verifies the published CJS and UMD contracts. Release is deliberately two steps: make release-patch bumps package.json, commits and tags locally, and make publish does the rest. That separation is worth knowing if you fork.
Licence is MIT, declared in package.json and present as a LICENSE file at the repository root. MIT permits commercial and closed-source use with the copyright notice retained; I am not a lawyer and this is not legal advice, so read LICENSE yourself if your organisation has a policy review. The practical upgrade cost is low: no runtime dependencies are listed in the package.json excerpt, and the API surface you would migrate is the props table.
Editorial conclusion
Adopt react-draggable when you need one element or a short list of elements to follow the pointer and you are willing to manage layout yourself: the README shows the install command, the nodeRef pattern and the DraggableCore escape hatch, and that is the whole surface. Do not adopt it if you need sortable lists, cross-container drop targets or accessibility semantics, because the README describes none of those and points to React-Resizable and React-Grid-Layout only as consumers of DraggableCore. Before committing, verify in your own project that nodeRef is wired on every Draggable child (the README states it is required for React Strict Mode), that no existing CSS transform sits on the element you are wrapping, and that your bundler resolves the exports map in package.json, since the published entry points are build/cjs/cjs.js and build/cjs/cjs.mjs rather than a top-level index.
Frequently asked questions
What is draggable?
In this context it is react-draggable, a React component that makes an existing element draggable. According to the README, it wraps the element, extends it with event handlers and styles, and moves it using CSS transforms without creating a wrapper element in the DOM.
How to use react draggable?
Import Draggable, create a ref with useRef, and pass that ref to both the nodeRef prop and the child element. The README's Quick Start shows this pattern and notes that nodeRef is required for React Strict Mode.
How do I install react draggable?
Run npm install react-draggable, or yarn add react-draggable. The README also shows ES module and CommonJS import forms, and states that TypeScript types are included.
What is react draggable?
It is a component that makes an element draggable by applying CSS transforms to it, exported alongside DraggableCore, which provides drag callbacks without managing state or styles. The README describes Draggable as the batteries-included option.
How does react draggable compare with dnd-kit?
react-draggable tracks coordinates and applies a transform; it has no drop targets, collision detection or sortable ordering in its documented API. dnd-kit and react-dnd model a drag as a transfer between a source and a target, which is a different abstraction.
How does react draggable compare with react-dnd?
Both react-dnd and react-draggable are listed as alternatives to each other in search, but their models differ. react-draggable exposes a props table and a pair of coordinates, while react-dnd is built around dragging between a source and a target rather than moving one element around a page.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/react-grid-layout-react-draggable)