react-dnd vs react-draggable vs react-zoom-pan-pinch
Interactive UI Libraries for Drag, Drop, and Zoom in React
react-dndreact-draggablereact-zoom-pan-pinchSimilar Packages:

Interactive UI Libraries for Drag, Drop, and Zoom in React

react-dnd, react-draggable, and react-zoom-pan-pinch are React libraries that enable rich user interactions, but they address fundamentally different use cases. react-dnd provides a comprehensive drag-and-drop framework for transferring data between designated drop targets, commonly used in task boards or file organizers. react-draggable offers simple, direct control for making any element draggable anywhere on the screen, ideal for floating UI components like modals or widgets. react-zoom-pan-pinch implements multi-touch gestures — including zoom, pan, and pinch — for navigating large visual content such as maps, diagrams, or images. While all involve manipulating elements on screen, their underlying models, APIs, and intended scenarios differ significantly.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-dnd021,637231 kB474-MIT
react-draggable09,290243 kB2149 months agoMIT
react-zoom-pan-pinch01,851441 kB159a year agoMIT

Drag, Drop, and Zoom: Choosing the Right Interaction Library for React

When building interactive UIs in React — think Kanban boards, diagram editors, or image viewers — you’ll often need to support drag-and-drop, free dragging, or zooming/panning. The three libraries react-dnd, react-draggable, and react-zoom-pan-pinch each solve distinct interaction problems. Despite all involving "moving things around," they’re built for different use cases, with different mental models and APIs. Let’s compare them head-to-head.

🖱️ Core Interaction Model: What Each Library Actually Does

react-dnd is a drag-and-drop framework inspired by the HTML5 Drag and Drop API but built entirely in JavaScript. It’s designed for transferring data between drop targets, like moving a card from one column to another. It uses a provider-based context system and separates concerns into drag sources and drop targets.

// react-dnd: Moving an item between lists
import { useDrag, useDrop } from 'react-dnd';

const Item = ({ id, moveItem }) => {
  const [{ isDragging }, drag] = useDrag(() => ({
    type: 'item',
    item: { id },
    collect: (monitor) => ({ isDragging: !!monitor.isDragging() })
  }));

  return <div ref={drag} style={{ opacity: isDragging ? 0.5 : 1 }}>Drag me</div>;
};

const DropZone = ({ acceptType, onDrop }) => {
  const [{ isOver }, drop] = useDrop(() => ({
    accept: acceptType,
    drop: (item) => onDrop(item),
    collect: (monitor) => ({ isOver: !!monitor.isOver() })
  }));

  return <div ref={drop} style={{ background: isOver ? '#eee' : '#fff' }}>Drop here</div>;
};

react-draggable enables free-form dragging of a single element anywhere on the screen. It doesn’t care about drop zones or data transfer — it just lets you move something and gives you position updates. Think resizable modals, draggable avatars, or movable widgets.

// react-draggable: Move an element freely
import Draggable from 'react-draggable';

function Widget() {
  return (
    <Draggable>
      <div style={{ width: 100, height: 100, background: 'blue' }} />
    </Draggable>
  );
}

// Or with callbacks
<Draggable
  onStop={(e, data) => console.log('Final position:', data.x, data.y)}
>
  <div>Draggable Box</div>
</Draggable>

react-zoom-pan-pinch adds multi-touch gestures (zoom, pan, pinch) to any container. It’s ideal for maps, diagrams, or image viewers where users need to explore a large canvas. It manages internal state for scale and position and exposes controls via a render prop or hook.

// react-zoom-pan-pinch: Interactive canvas navigation
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';

function ImageViewer({ src }) {
  return (
    <TransformWrapper>
      {({ zoomIn, zoomOut, resetTransform }) => (
        <>
          <div>
            <button onClick={() => zoomIn()}>+</button>
            <button onClick={() => zoomOut()}>–</button>
            <button onClick={() => resetTransform()}>Reset</button>
          </div>
          <TransformComponent>
            <img src={src} alt="Zoomable" />
          </TransformComponent>
        </>
      )}
    </TransformWrapper>
  );
}

🔧 State Management and Control

Each library handles internal state differently, which affects how much control you have.

react-dnd keeps drag state in React Context (via <DndProvider>). You don’t manage coordinates directly — instead, you respond to drop events with payload data. Positional feedback (like previews) is handled via its built-in backend system (HTML5, Touch, or custom).

react-draggable gives you full access to the current {x, y} position through callbacks (onDrag, onStop) or by controlling the component yourself with position and onDrag. It’s unopinionated about rendering — you provide the DOM node.

react-zoom-pan-pinch encapsulates all transform state (scale, x, y) internally but exposes it via the render prop or useTransformContext hook. You can read or update it programmatically:

// Accessing transform state
<TransformWrapper>
  {({ state: { scale, positionX, positionY } }) => (
    <div>Scale: {scale.toFixed(2)}</div>
  )}
</TransformWrapper>

🎯 When to Use Which? Real-World Scenarios

Scenario 1: Task Board (Trello-style)

You need to drag cards between columns, with visual feedback during drag and data updates on drop.

  • Best choice: react-dnd
  • Why? Built for structured drag-and-drop with clear source/target semantics. Handles accessibility, preview rendering, and backend abstraction out of the box.

Scenario 2: Floating Toolbar or Movable Chat Widget

A UI element that users can reposition anywhere on the page, but doesn’t interact with other elements.

  • Best choice: react-draggable
  • Why? Lightweight, zero-config for basic dragging. No need for drop zones or data payloads.

Scenario 3: Interactive Diagram or Map Viewer

Users need to zoom into details, pan across a large SVG or image, and possibly reset the view.

  • Best choice: react-zoom-pan-pinch
  • Why? Provides smooth, performant gesture handling with keyboard and mouse support. Manages complex transform math so you don’t have to.

⚠️ Common Misuses and Pitfalls

  • Don’t use react-dnd for free dragging. It’s overkill if you don’t need drop targets or data transfer. You’ll fight its abstractions.
  • Don’t use react-draggable for list reordering. It doesn’t handle collision detection, auto-scrolling, or drop logic — you’d have to build all that yourself.
  • Don’t use react-zoom-pan-pinch for drag-and-drop. It has no concept of “dropping” items or transferring data between zones.

🔄 Can They Work Together?

Yes — and sometimes you need to. For example, a diagram editor might use:

  • react-zoom-pan-pinch for canvas navigation
  • react-draggable for moving individual nodes within the canvas
  • react-dnd for importing new nodes from a sidebar palette

In such cases, ensure event propagation doesn’t conflict (e.g., dragging a node shouldn’t also pan the canvas). Libraries like react-zoom-pan-pinch offer pansDisabled or event filtering to help.

📌 Summary Table

Featurereact-dndreact-draggablereact-zoom-pan-pinch
Primary Use CaseData transfer between zonesFree movement of elementsZoom/pan/pinch on content
State OwnershipContext-managedCallback-driven or controlledInternal + exposed via hook
Drop Logic✅ Built-in❌ Not applicable❌ Not applicable
Gesture SupportBasic (via backends)Mouse/touch drag only✅ Multi-touch, wheel, keys
Best ForLists, grids, reorderable UIFloating UI, modals, widgetsMaps, images, large canvases

💡 Final Recommendation

Ask yourself: What is the user trying to accomplish?

  • If they’re moving data from A to B, choose react-dnd.
  • If they’re repositioning a single thing freely, choose react-draggable.
  • If they’re exploring a zoomable space, choose react-zoom-pan-pinch.

These libraries solve orthogonal problems. Picking the right one avoids unnecessary complexity and keeps your interaction code clean, maintainable, and performant.

How to Choose: react-dnd vs react-draggable vs react-zoom-pan-pinch

  • react-dnd:

    Choose react-dnd when you need structured drag-and-drop interactions with clear source and target semantics, such as reordering items in a list, moving cards between columns, or transferring data between UI zones. It handles accessibility, preview rendering, and backend abstraction (HTML5, touch) out of the box, but is overkill if you only need free-form dragging without drop logic.

  • react-draggable:

    Choose react-draggable when you need to make a single element freely draggable anywhere on the page without drop targets or data transfer — for example, movable chat widgets, resizable panels, or floating toolbars. It’s lightweight, requires minimal setup, and gives you direct access to position updates, but doesn’t support collision detection, auto-scrolling, or list reordering natively.

  • react-zoom-pan-pinch:

    Choose react-zoom-pan-pinch when users need to explore large visual content through zooming, panning, and pinch gestures, such as in map viewers, diagram editors, or image galleries. It provides smooth, performant gesture handling with keyboard and mouse support, but is not designed for drag-and-drop or element repositioning outside of canvas navigation.

README for react-dnd

npm version npm downloads Build Status

React DnD

Drag and Drop for React.

See the docs, tutorials and examples on the website:

http://react-dnd.github.io/react-dnd/

See the changelog on the Releases page:

https://github.com/react-dnd/react-dnd/releases

Big thanks to BrowserStack for letting the maintainers use their service to debug browser issues.