apps/docs/react/guides/migration.mdx
```diff
"dependencies": {
- "@dnd-kit/core": "^x.x.x"
- "@dnd-kit/sortable": "^x.x.x"
- "@dnd-kit/utilities": "^x.x.x"
+ "@dnd-kit/react": "^x.x.x"
+ "@dnd-kit/helpers": "^x.x.x"
}
```
After updating your package.json, install the new dependencies with your package manager of choice.
<CodeGroup>
```tsx Before
import {DndContext} from '@dnd-kit/core';
function App() {
return (
<DndContext
onDragStart={({active}) => {
console.log(`Started dragging ${active.id}`);
}}
onDragEnd={({active, over}) => {
if (over) {
console.log(`Dropped ${active.id} over ${over.id}`);
}
}}
onDragCancel={({active}) => {
console.log(`Cancelled dragging ${active.id}`);
}}
>
<YourComponents />
</DndContext>
);
}
```
```tsx After {1,6-8,10-24}
import {DragDropProvider} from '@dnd-kit/react';
function App() {
return (
<DragDropProvider
onDragStart={(event, manager) => {
const {operation} = event;
console.log(`Started dragging ${operation.source.id}`);
}}
onDragEnd={(event, manager) => {
const {operation, canceled} = event;
const {source, target} = operation;
if (canceled) {
// Replaces onDragCancel
console.log(`Cancelled dragging ${source.id}`);
return;
}
if (target) {
console.log(`Dropped ${source.id} over ${target.id}`);
// Access rich data
console.log('Source data:', source.data);
console.log('Drop position:', operation.position.current);
}
}}
>
<YourComponents />
</DragDropProvider>
);
}
```
</CodeGroup>
<Info>
The new provider gives you access to the `manager` instance in event handlers, enabling more advanced control over the drag and drop system.
</Info>
<CodeGroup>
```tsx Before
function DraggableItem({id}) {
const {
attributes,
listeners,
setNodeRef,
transform
} = useDraggable({
id
});
return (
<div
ref={setNodeRef}
{...listeners}
{...attributes}
style={{
transform: CSS.Transform.toString(transform)
}}
>
Item {id}
</div>
);
}
```
```tsx After {2-4,7-8}
function DraggableItem({id}) {
const draggable = useDraggable({
id,
});
return (
<div
ref={draggable.ref}
className={isDragging ? 'dragging' : ''}
>
Item {id}
</div>
);
}
```
</CodeGroup>
<CodeGroup>
```tsx Before
function Dropzone() {
const {setNodeRef, isOver} = useDroppable({
id: 'drop-zone'
});
return (
<div
ref={setNodeRef}
style={{
background: isOver ? 'lightblue' : 'white'
}}
>
Drop here
</div>
);
}
```
```tsx After {2,8,10}
function Dropzone() {
const droppable = useDroppable({
id: 'drop-zone'
});
return (
<div
ref={droppable.ref}
style={{
background: droppable.isDropTarget ? 'green' : 'white'
}}
>
Drop here
</div>
);
}
```
</CodeGroup>
<CodeGroup>
```tsx Before
function App() {
const [activeId, setActiveId] = useState(null);
return (
<DndContext
onDragStart={() => setActiveId('item')}
onDragEnd={() => setActiveId(null)}
>
<Draggable id="item" />
<DragOverlay>
{activeId ? <Item id={activeId} /> : null}
</DragOverlay>
</DndContext>
);
}
```
```tsx After {2,5,7-9}
function App() {
return (
<DragDropProvider>
<Draggable id="item" />
<DragOverlay>
{source => (
<Item id={source.id} />
)}
</DragOverlay>
</DragDropProvider>
);
}
```
</CodeGroup>
<Warning>
Only render the `DragOverlay` component once per `DragDropProvider`. The hooks have no effect when used within the overlay.
</Warning>
<CodeGroup>
```tsx Before
import {useSortable} from '@dnd-kit/sortable';
function SortableItem({id, index}) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition
} = useSortable({
id,
index
});
return (
<div
ref={setNodeRef}
{...attributes}
{...listeners}
style={{
transform: CSS.Transform.toString(transform),
transition
}}
>
Item {id}
</div>
);
}
```
```tsx After {1,4-7,10-11}
import {useSortable} from '@dnd-kit/react/sortable';
function SortableItem({id, index}) {
const sortable = useSortable({
id,
index
});
return (
<div
ref={sortable.ref}
className={sortable.isDragging ? 'dragging' : undefined}
>
Item {id}
</div>
);
}
```
</CodeGroup>
Use the array manipulation helpers from `@dnd-kit/helpers` to handle reordering.