Skip to main content
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

children
React.ReactNode
required
The components that will use drag and drop functionality. Must include at least one draggable or droppable component.
manager
DragDropManager
A custom DragDropManager instance. If not provided, a new instance is created automatically.
plugins
Plugin[]
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>
modifiers
Modifier[]
Array of modifiers that transform drag coordinates during drag operations.
import {restrictToHorizontalAxis} from '@dnd-kit/modifiers';

<DragDropProvider modifiers={[restrictToHorizontalAxis]}>
  {children}
</DragDropProvider>
sensors
Sensor[]
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:
operation
DragOperation
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
canceled
boolean
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>

Build docs developers (and LLMs) love