
Product
Introducing Reports: An Extensible Reporting Framework for Socket Data
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.
react-optimized-dnd
Advanced tools
A React package for building performant drag-and-drop interfaces. Provides context provider, hooks, and type definitions for flexible, optimized DnD in React apps.
A React package for building performant drag-and-drop interfaces. Provides context provider, hooks, and type definitions for flexible, optimized DnD in React apps.
npm install react-optimized-dnd
or
yarn add react-optimized-dnd
Below is a minimal Trello-like board with draggable cards and droppable columns.
import { useState } from 'react';
import { ReactOptimizedDndProvider, useDraggable, useDroppable } from 'react-optimized-dnd';
const columnsData = [
[
{ title: 'Card 1', description: 'Desc 1', color: '#60a5fa' },
{ title: 'Card 2', description: 'Desc 2', color: '#f59e42' },
],
[{ title: 'Card 3', description: 'Desc 3', color: '#10b981' }],
[{ title: 'Card 4', description: 'Desc 4', color: '#f43f5e' }],
];
function Card({ index, columnIndex, title, description, color }) {
const { droppableRef, isOver } = useDroppable({ data: { index, columnIndex, type: 'card' } });
const { handleRef, deltaPos, isDragging } = useDraggable({
data: { index, columnIndex, type: 'card' },
});
return (
<div
ref={droppableRef}
style={{
border: isDragging ? '1px solid #e5e7eb' : '1px solid transparent',
background: isDragging ? '#fafaf9' : 'white',
borderRadius: 6,
}}
>
<div
ref={handleRef}
style={{
cursor: isDragging ? 'grabbing' : 'grab',
background: isDragging ? '#93c5fd' : '#fff',
borderRadius: 6,
padding: 12,
boxShadow: '0 1px 2px #0001',
transform: `translate(${deltaPos.x}px, ${deltaPos.y}px)`,
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div
style={{
width: 24,
height: 24,
borderRadius: '50%',
background: color,
color: '#fff',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 700,
}}
>
{title.charAt(0)}
</div>
<div>
<div style={{ fontWeight: 500 }}>{title}</div>
<div style={{ fontSize: 12, color: '#6b7280' }}>{description}</div>
</div>
</div>
</div>
</div>
);
}
function Column({ children, index }) {
const { droppableRef, isOver } = useDroppable({ data: { index, type: 'column' } });
return (
<div
ref={droppableRef}
style={{
width: 280,
background: '#f3f4f6',
borderRadius: 8,
padding: 16,
display: 'flex',
flexDirection: 'column',
gap: 8,
}}
>
{children}
{isOver && (
<div
style={{
height: 48,
background: '#dbeafe',
border: '1px solid #bfdbfe',
borderRadius: 6,
}}
/>
)}
</div>
);
}
export default function Example() {
const [columns, setColumns] = useState(columnsData);
return (
<div style={{ display: 'flex', gap: 16 }}>
<ReactOptimizedDndProvider
onDragStart={() => {}}
onDragEnd={(state) => {
const dragging = state.draggingElement.data;
const over = state.overElement.data;
if (!dragging || !over) return;
if (over.type === 'card') {
const newColumns = [...columns];
const targetCol = over.columnIndex;
const targetIdx = over.index;
const dragCol = dragging.columnIndex;
const dragIdx = dragging.index;
const item = newColumns[dragCol][dragIdx];
newColumns[dragCol] = newColumns[dragCol].filter((_, i) => i !== dragIdx);
newColumns[targetCol].splice(targetIdx, 0, item);
setColumns(newColumns);
return;
}
if (over.type === 'column') {
const newColumns = [...columns];
const targetCol = over.index;
const dragCol = dragging.columnIndex;
const dragIdx = dragging.index;
const item = newColumns[dragCol][dragIdx];
newColumns[dragCol] = newColumns[dragCol].filter((_, i) => i !== dragIdx);
newColumns[targetCol] = [...newColumns[targetCol], item];
setColumns(newColumns);
return;
}
}}
onDragOver={() => {}}
>
{columns.map((column, columnIndex) => (
<Column key={columnIndex} index={columnIndex}>
{column.map((item, cardIndex) => (
<Card key={cardIndex} index={cardIndex} columnIndex={columnIndex} {...item} />
))}
</Column>
))}
</ReactOptimizedDndProvider>
</div>
);
}
ReactOptimizedDndProviderWrap your app or a subtree to enable drag-and-drop. Accepts optional callbacks:
onDragStart: (state) => voidonDragEnd: (state) => voidonDragOver: (state) => voiduseDraggableHook to make an element draggable.
data: Any object to identify the draggable (required){ handleRef, deltaPos, isDragging }useDroppableHook to make an element a drop target.
data: Any object to identify the droppable (required){ droppableRef, isOver }MIT
FAQs
A React package for building performant drag-and-drop interfaces. Provides context provider, hooks, and type definitions for flexible, optimized DnD in React apps.
We found that react-optimized-dnd demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.