DragDropProvider is the root component that wraps your drag and drop interface. It creates a DragDropManager instance, manages sensors and plugins, and provides drag and drop context to all child components.
Usage
import {DragDropProvider} from '@dnd-kit/react';
function App() {
return (
<DragDropProvider
onDragEnd={(event) => {
console.log('Drag ended', event);
}}
>
{/* Your drag and drop components */}
</DragDropProvider>
);
}
Props
The components that will use drag and drop functionality. Must include at least one draggable or droppable component.
A custom DragDropManager instance. If not provided, a new instance is created automatically.
Array of plugins to customize drag and drop behavior. Plugins can modify coordinates, provide feedback, or add custom functionality.import {Feedback} from '@dnd-kit/dom';
<DragDropProvider plugins={[new Feedback()]}>
{children}
</DragDropProvider>
Array of modifiers that transform drag coordinates during drag operations.import {restrictToHorizontalAxis} from '@dnd-kit/modifiers';
<DragDropProvider modifiers={[restrictToHorizontalAxis]}>
{children}
</DragDropProvider>
Array of sensors that detect drag interactions. By default, includes PointerSensor and KeyboardSensor.import {PointerSensor} from '@dnd-kit/react';
<DragDropProvider sensors={[new PointerSensor()]}>
{children}
</DragDropProvider>
Event Handlers
onBeforeDragStart
(event: BeforeDragStartEvent, manager: DragDropManager) => void
Called before a drag operation starts. Use this to prevent or modify drag operations.<DragDropProvider
onBeforeDragStart={(event, manager) => {
console.log('About to start dragging', event.source);
}}
>
{children}
</DragDropProvider>
onDragStart
(event: DragStartEvent, manager: DragDropManager) => void
Called when a drag operation starts.<DragDropProvider
onDragStart={(event, manager) => {
console.log('Drag started', event.operation.source);
}}
>
{children}
</DragDropProvider>
onDragMove
(event: DragMoveEvent, manager: DragDropManager) => void
Called continuously while dragging. Use sparingly as this fires frequently.<DragDropProvider
onDragMove={(event, manager) => {
console.log('Current position', event.operation.position);
}}
>
{children}
</DragDropProvider>
onDragOver
(event: DragOverEvent, manager: DragDropManager) => void
Called when dragging over a droppable element.<DragDropProvider
onDragOver={(event, manager) => {
console.log('Dragging over', event.operation.target);
}}
>
{children}
</DragDropProvider>
onDragEnd
(event: DragEndEvent, manager: DragDropManager) => void
Called when a drag operation ends. This is where you typically update your application state.<DragDropProvider
onDragEnd={(event, manager) => {
if (event.canceled) return;
const sourceId = event.operation.source.id;
const targetId = event.operation.target?.id;
// Update your state based on the drop
updateItems(sourceId, targetId);
}}
>
{children}
</DragDropProvider>
onCollision
(event: CollisionEvent, manager: DragDropManager) => void
Called when collision detection identifies potential drop targets.
Event Object Properties
All event handlers receive an event object with the following structure:
The current drag operation containing:
source — The draggable element being dragged
target — The current drop target (if any)
position — Current position of the drag source
status — Current status of the operation
Whether the drag operation was canceled (only in onDragEnd).
Complete Example
import {DragDropProvider, useDraggable, useDroppable} from '@dnd-kit/react';
import {Feedback} from '@dnd-kit/dom';
import {useState} from 'react';
function App() {
const [items, setItems] = useState(['A', 'B', 'C']);
const [activeId, setActiveId] = useState(null);
return (
<DragDropProvider
plugins={[new Feedback()]}
onBeforeDragStart={(event) => {
console.log('Starting drag:', event.source.id);
}}
onDragStart={(event) => {
setActiveId(event.operation.source.id);
}}
onDragOver={(event) => {
console.log('Over target:', event.operation.target?.id);
}}
onDragEnd={(event) => {
setActiveId(null);
if (event.canceled) return;
const {source, target} = event.operation;
if (target) {
// Handle the drop
console.log(`Dropped ${source.id} on ${target.id}`);
}
}}
>
<div>
{items.map((id) => (
<DraggableItem key={id} id={id} />
))}
</div>
<DroppableArea id="trash" />
</DragDropProvider>
);
}
Type Parameters
DragDropProvider accepts generic type parameters for type-safe data:
interface MyData {
label: string;
category: string;
}
<DragDropProvider<MyData>
onDragEnd={(event) => {
// event.operation.source.data is typed as MyData
console.log(event.operation.source.data.label);
}}
>
{children}
</DragDropProvider>