Drag and Drop for React applications with hooks-based API and TypeScript support
npx @tessl/cli install tessl/npm-react-dnd@16.0.00
# React DnD
1
2
React DnD is a comprehensive drag and drop library for React applications that provides a declarative approach to complex drag and drop interactions. Built with TypeScript, this library offers a flexible API through React hooks (useDrag, useDrop, useDragLayer) that enable developers to create sophisticated drag and drop interfaces with minimal boilerplate code.
3
4
## Package Information
5
6
- **Package Name**: react-dnd
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install react-dnd`
10
11
## Core Imports
12
13
```typescript
14
import { DndProvider, useDrag, useDrop, useDragLayer, DndContext, useDragDropManager } from "react-dnd";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { DndProvider, useDrag, useDrop, useDragLayer, DndContext, useDragDropManager } = require("react-dnd");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import React from "react";
27
import { DndProvider, useDrag, useDrop } from "react-dnd";
28
// Note: Backend is a separate package
29
import { HTML5Backend } from "react-dnd-html5-backend";
30
31
// Wrap your app with DndProvider
32
function App() {
33
return (
34
<DndProvider backend={HTML5Backend}>
35
<DragDropExample />
36
</DndProvider>
37
);
38
}
39
40
// Create a draggable item
41
function DraggableItem({ id, text }) {
42
const [{ isDragging }, drag] = useDrag({
43
type: "item",
44
item: { id, text },
45
collect: (monitor) => ({
46
isDragging: monitor.isDragging(),
47
}),
48
});
49
50
return (
51
<div ref={drag} style={{ opacity: isDragging ? 0.5 : 1 }}>
52
{text}
53
</div>
54
);
55
}
56
57
// Create a drop target
58
function DropTarget() {
59
const [{ isOver }, drop] = useDrop({
60
accept: "item",
61
drop: (item) => console.log("Dropped:", item),
62
collect: (monitor) => ({
63
isOver: monitor.isOver(),
64
}),
65
});
66
67
return (
68
<div ref={drop} style={{ backgroundColor: isOver ? "lightblue" : "white" }}>
69
Drop items here
70
</div>
71
);
72
}
73
```
74
75
## Architecture
76
77
React DnD is built around several key components:
78
79
- **Context System**: `DndProvider` and `DndContext` manage the drag and drop state across the component tree
80
- **Hook-based API**: Core hooks (`useDrag`, `useDrop`, `useDragLayer`) provide declarative drag and drop functionality
81
- **Monitor System**: Provides real-time information about drag and drop operations
82
- **Connector System**: Connects React components to DOM elements for drag and drop interactions
83
- **Backend Integration**: Pluggable backend system supporting HTML5 drag and drop, touch, and testing backends
84
85
## Capabilities
86
87
### Context and Provider
88
89
Core context and provider components for setting up React DnD in your application.
90
91
```typescript { .api }
92
function DndProvider<BackendContext, BackendOptions>(
93
props: DndProviderProps<BackendContext, BackendOptions>
94
): React.ReactElement;
95
96
type DndProviderProps<BackendContext, BackendOptions> =
97
| {
98
children?: React.ReactNode;
99
manager: DragDropManager;
100
}
101
| {
102
backend: BackendFactory;
103
children?: React.ReactNode;
104
context?: BackendContext;
105
options?: BackendOptions;
106
debugMode?: boolean;
107
};
108
```
109
110
[Context and Provider](./context-provider.md)
111
112
### Drag Source Hook
113
114
Hook for making components draggable with comprehensive configuration options.
115
116
```typescript { .api }
117
function useDrag<DragObject = unknown, DropResult = unknown, CollectedProps = unknown>(
118
specArg: FactoryOrInstance<DragSourceHookSpec<DragObject, DropResult, CollectedProps>>,
119
deps?: unknown[]
120
): [CollectedProps, ConnectDragSource, ConnectDragPreview];
121
122
interface DragSourceHookSpec<DragObject, DropResult, CollectedProps> {
123
type: SourceType;
124
item?: DragObject | DragObjectFactory<DragObject>;
125
options?: DragSourceOptions;
126
previewOptions?: DragPreviewOptions;
127
end?: (draggedItem: DragObject, monitor: DragSourceMonitor<DragObject, DropResult>) => void;
128
canDrag?: boolean | ((monitor: DragSourceMonitor<DragObject, DropResult>) => boolean);
129
isDragging?: (monitor: DragSourceMonitor<DragObject, DropResult>) => boolean;
130
collect?: (monitor: DragSourceMonitor<DragObject, DropResult>) => CollectedProps;
131
}
132
```
133
134
[Drag Sources](./drag-sources.md)
135
136
### Drop Target Hook
137
138
Hook for making components accept dropped items with flexible handling options.
139
140
```typescript { .api }
141
function useDrop<DragObject = unknown, DropResult = unknown, CollectedProps = unknown>(
142
specArg: FactoryOrInstance<DropTargetHookSpec<DragObject, DropResult, CollectedProps>>,
143
deps?: unknown[]
144
): [CollectedProps, ConnectDropTarget];
145
146
interface DropTargetHookSpec<DragObject, DropResult, CollectedProps> {
147
accept: TargetType;
148
options?: DropTargetOptions;
149
drop?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => DropResult | undefined;
150
hover?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => void;
151
canDrop?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => boolean;
152
collect?: (monitor: DropTargetMonitor<DragObject, DropResult>) => CollectedProps;
153
}
154
```
155
156
[Drop Targets](./drop-targets.md)
157
158
### Drag Layer Hook
159
160
Hook for creating custom drag previews and accessing global drag state.
161
162
```typescript { .api }
163
function useDragLayer<CollectedProps, DragObject = any>(
164
collect: (monitor: DragLayerMonitor<DragObject>) => CollectedProps
165
): CollectedProps;
166
```
167
168
[Drag Layer](./drag-layer.md)
169
170
### Drag Drop Manager Hook
171
172
Low-level hook for accessing the DragDropManager instance directly for advanced use cases.
173
174
```typescript { .api }
175
function useDragDropManager(): DragDropManager;
176
```
177
178
[Context and Provider](./context-provider.md)
179
180
### Utility Components
181
182
Utility components for advanced drag and drop scenarios.
183
184
```typescript { .api }
185
function DragPreviewImage(props: DragPreviewImageProps): React.ReactElement;
186
187
interface DragPreviewImageProps {
188
connect: ConnectDragPreview;
189
src: string;
190
}
191
```
192
193
[Utilities](./utilities.md)
194
195
## Types
196
197
### Core Types
198
199
```typescript { .api }
200
// Core identifiers and types (from dnd-core)
201
type Identifier = string | symbol;
202
type SourceType = string | symbol;
203
type TargetType = string | symbol | string[] | symbol[];
204
205
// Drag and drop managers and contexts
206
interface DndContextType {
207
dragDropManager: DragDropManager | undefined;
208
}
209
210
interface DragDropManager {
211
getMonitor(): DragDropMonitor;
212
getBackend(): Backend;
213
getRegistry(): HandlerRegistry;
214
dispatch(action: any): void;
215
}
216
217
interface HandlerManager {
218
receiveHandlerId(handlerId: Identifier | null): void;
219
getHandlerId(): Identifier | null;
220
}
221
222
interface MonitorEventEmitter {
223
subscribeToStateChange(
224
fn: () => void,
225
options?: { handlerIds?: Identifier[] }
226
): Unsubscribe;
227
}
228
229
type Unsubscribe = () => void;
230
type BackendFactory<BackendContext = any, BackendOptions = any> = (
231
manager: DragDropManager,
232
context?: BackendContext,
233
options?: BackendOptions
234
) => Backend;
235
236
interface Backend {
237
setup(): void;
238
teardown(): void;
239
connectDragSource(sourceId: any, node: any, options: any): () => void;
240
connectDragPreview(sourceId: any, node: any, options: any): () => void;
241
connectDropTarget(targetId: any, node: any, options: any): () => void;
242
}
243
244
interface HandlerRegistry {
245
addSource(type: string, source: any): Identifier;
246
addTarget(type: string, target: any): Identifier;
247
removeSource(sourceId: Identifier): void;
248
removeTarget(targetId: Identifier): void;
249
getSource(sourceId: Identifier, includePinned?: boolean): any;
250
getTarget(targetId: Identifier, includePinned?: boolean): any;
251
getSourceType(sourceId: Identifier): string | null;
252
getTargetType(targetId: Identifier): string | null;
253
isPinned(handlerId: Identifier): boolean;
254
pin(handlerId: Identifier): void;
255
unpin(handlerId: Identifier): void;
256
}
257
258
interface DragDropMonitor extends DragSourceMonitor, DropTargetMonitor, DragLayerMonitor {
259
// Additional methods specific to the combined monitor
260
}
261
262
// Connector functions
263
type ConnectDragSource = DragElementWrapper<DragSourceOptions>;
264
type ConnectDropTarget = DragElementWrapper<any>;
265
type ConnectDragPreview = DragElementWrapper<DragPreviewOptions>;
266
type ConnectableElement = React.RefObject<any> | React.ReactElement | Element | null;
267
268
// Utility types
269
type FactoryOrInstance<T> = T | (() => T);
270
type DragObjectFactory<T> = (monitor: DragSourceMonitor<T>) => T | null;
271
272
// Coordinate system
273
interface XYCoord {
274
x: number;
275
y: number;
276
}
277
```
278
279
### Monitor Interfaces
280
281
```typescript { .api }
282
interface DragSourceMonitor<DragObject = unknown, DropResult = unknown> extends HandlerManager, MonitorEventEmitter {
283
canDrag(): boolean;
284
isDragging(): boolean;
285
getItemType(): Identifier | null;
286
getItem<T = DragObject>(): T;
287
getDropResult<T = DropResult>(): T | null;
288
didDrop(): boolean;
289
getInitialClientOffset(): XYCoord | null;
290
getInitialSourceClientOffset(): XYCoord | null;
291
getClientOffset(): XYCoord | null;
292
getDifferenceFromInitialOffset(): XYCoord | null;
293
getSourceClientOffset(): XYCoord | null;
294
getTargetIds(): Identifier[];
295
}
296
297
interface DropTargetMonitor<DragObject = unknown, DropResult = unknown> extends HandlerManager, MonitorEventEmitter {
298
canDrop(): boolean;
299
isOver(options?: { shallow?: boolean }): boolean;
300
getItemType(): Identifier | null;
301
getItem<T = DragObject>(): T;
302
getDropResult<T = DropResult>(): T | null;
303
didDrop(): boolean;
304
getInitialClientOffset(): XYCoord | null;
305
getInitialSourceClientOffset(): XYCoord | null;
306
getClientOffset(): XYCoord | null;
307
getDifferenceFromInitialOffset(): XYCoord | null;
308
getSourceClientOffset(): XYCoord | null;
309
}
310
311
interface DragLayerMonitor<DragObject = unknown> {
312
isDragging(): boolean;
313
getItemType(): Identifier | null;
314
getItem<T = DragObject>(): T;
315
getInitialClientOffset(): XYCoord | null;
316
getInitialSourceClientOffset(): XYCoord | null;
317
getClientOffset(): XYCoord | null;
318
getDifferenceFromInitialOffset(): XYCoord | null;
319
getSourceClientOffset(): XYCoord | null;
320
}
321
```
322
323
### Option Interfaces
324
325
```typescript { .api }
326
interface DragSourceOptions {
327
dropEffect?: string;
328
}
329
330
interface DragPreviewOptions {
331
captureDraggingState?: boolean;
332
anchorX?: number;
333
anchorY?: number;
334
offsetX?: number;
335
offsetY?: number;
336
}
337
338
type DropTargetOptions = any;
339
```