react-beautiful-dnd, react-dnd, and react-sortable-hoc are three distinct approaches to implementing drag-and-drop (DnD) interactions in React. react-beautiful-dnd offers an opinionated, accessible solution optimized for vertical lists and boards, enforcing strict design patterns. react-dnd provides a low-level, highly flexible API based on the HTML5 Drag and Drop backend, allowing for complex custom interactions and multiple backends. react-sortable-hoc uses Higher-Order Components (HOCs) to inject sorting logic, focusing primarily on simple list reordering but relying on older React patterns that conflict with modern Hooks.
Implementing drag-and-drop (DnD) in React is deceptively complex. It involves managing pointer events, calculating layout shifts, handling accessibility focus states, and synchronizing DOM updates without causing performance jank. The three libraries in question โ react-beautiful-dnd, react-dnd, and react-sortable-hoc โ represent three different philosophical approaches to solving this problem. Let's break down how they handle architecture, component composition, and real-world constraints.
The way these libraries integrate with your component tree defines your entire development experience. This is often the first architectural decision you make.
react-beautiful-dnd uses a render-prop and hook-friendly approach. It exposes context via components like <DragDropContext>, <Droppable>, and <Draggable>. You provide a function child to access the provided props. This pattern works seamlessly with modern functional components and Hooks.
// react-beautiful-dnd: Render prop pattern
import { Draggable } from 'react-beautiful-dnd';
function TaskItem({ task, index }) {
return (
<Draggable draggableId={task.id} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{ ...provided.draggableProps.style }}
>
{task.content}
</div>
)}
</Draggable>
);
}
react-dnd historically relied on Higher-Order Components (HOCs) but now fully supports Hooks (useDrag, useDrop). The Hook API is cleaner and avoids the "wrapper hell" of the old HOC approach. It separates the logic of "what can be dragged" from "where it can be dropped" explicitly.
// react-dnd: Hooks API
import { useDrag, useDrop } from 'react-dnd';
function TaskItem({ task }) {
const [{ isDragging }, dragRef] = useDrag(() => ({
type: 'TASK',
item: { id: task.id },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}));
return (
<div ref={dragRef} style={{ opacity: isDragging ? 0.5 : 1 }}>
{task.content}
</div>
);
}
react-sortable-hoc relies exclusively on Higher-Order Components (HOCs). You must wrap your component with sortableElement and sortableHandle. This pattern is problematic in modern React because it forces class components or creates complex nesting when trying to use Hooks inside the wrapped component. It injects props rather than exposing a clean API.
// react-sortable-hoc: HOC pattern
import { sortableElement, sortableHandle } from 'react-sortable-hoc';
const DragHandle = sortableHandle(() => <span>:::</span>);
const SortableItem = sortableElement(({ value }) => (
<div>
<DragHandle />
{value}
</div>
));
// Usage requires passing extra props like 'index' and 'listenTosort'
// <SortableItem index={i} value={item} />
Your choice often depends on whether you are building a simple sorted list or a complex interactive canvas.
react-beautiful-dnd is strictly opinionated. It is designed for vertical lists and grid-based boards (like Trello). It enforces specific rules: you generally cannot drag items outside their immediate parent droppable without complex workarounds. It handles the heavy lifting of accessibility and animations automatically but restricts you from doing weird things.
// react-beautiful-dnd: Strict list structure
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="list">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{/* ... */}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
react-dnd is unopinionated and universal. You can drag items between windows, implement custom gestures, or create games. It doesn't assume a list structure. You define the "types" of items and how they interact. This flexibility comes with the cost of implementing your own preview layers and collision logic if you need them.
// react-dnd: Custom drop zone logic
function GameBoard() {
const [{ canDrop, isOver }, dropRef] = useDrop(() => ({
accept: 'GAME_PIECE',
drop: (item) => { /* custom logic */ },
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
}));
return <div ref={dropRef} className={isOver ? 'active' : ''}>Drop Zone</div>;
}
react-sortable-hoc is scoped purely to sorting lists. It assumes a 1:1 relationship between items and indices. It lacks native support for nested lists, grids, or complex board layouts without significant hacking. It is a single-purpose tool for reordering arrays.
// react-sortable-hoc: Simple array sorting
const SortableList = sortableContainer(({ items }) => (
<ul>
{items.map((value, index) => (
<SortableItem key={`item-${index}`} index={index} value={value} />
))}
</ul>
));
Accessibility (a11y) is the hardest part of DnD to get right. Moving DOM nodes while maintaining keyboard focus and screen reader announcements requires rigorous engineering.
react-beautiful-dnd is the gold standard here. It automatically manages ARIA attributes, keyboard navigation (arrow keys to move), and focus retention. It also includes a physics-based animation engine that smoothly transitions elements without layout thrashing. You get this out of the box.
// react-beautiful-dnd: Automatic a11y and animation
// No extra code needed for keyboard support or smooth sliding
<Draggable draggableId="task-1" index={0}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
Accessible Task
</div>
)}
</Draggable>
react-dnd provides the logic but not the UI polish. It does not automatically animate elements or manage ARIA states for you. You must build the visual feedback (using react-dnd-html5-backend or custom layers) and ensure keyboard accessibility manually. This is powerful but risky for teams without deep a11y expertise.
// react-dnd: Manual animation and a11y required
// You must calculate styles based on drag state
const [{ isDragging }, dragRef] = useDrag({
type: 'BOX',
item: { id },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
// You must apply transforms manually for smooth movement
const style = { opacity: isDragging ? 0.4 : 1, transform: 'translate(...)' };
react-sortable-hoc provides basic keyboard support (pressing space to lift, arrows to move), but it is less robust than react-beautiful-dnd. The animations are CSS-transform based and can sometimes struggle with complex layouts or overflow containers. It feels lighter but less polished.
// react-sortable-hoc: Basic helper props
// Helper functions provided for transitions, but less configurable
const SortableItem = sortableElement(({ value, style }) => (
<li style={style}>{value}</li>
));
A critical architectural factor is the long-term viability of the library.
react-beautiful-dnd is in maintenance mode. The original maintainers have shifted focus to a new library called @dnd-kit, which is more modular and supports a wider range of use cases. While react-beautiful-dnd is stable and widely used, new projects should strongly consider @dnd-kit or react-dnd to avoid future migration costs. It is not "dead," but it is not evolving.
react-dnd is actively maintained and widely adopted in enterprise environments. Its decoupled architecture (core logic separate from backend) ensures it remains relevant even as React evolves. It is a safe long-term bet for complex applications.
react-sortable-hoc has seen very little activity recently. Its reliance on HOCs makes it increasingly difficult to integrate with modern React patterns (like concurrent rendering and server components). It is effectively legacy technology.
| Feature | react-beautiful-dnd | react-dnd | react-sortable-hoc |
|---|---|---|---|
| Primary Use Case | Lists & Kanban Boards | Complex, Custom Interactions | Simple List Sorting |
| Integration Pattern | Render Props / Context | Hooks (or HOCs) | Higher-Order Components (HOC) |
| Accessibility | โ Excellent (Built-in) | โ ๏ธ Manual Implementation | โช Basic Support |
| Animations | โ Smooth, Physics-based | โ ๏ธ Manual / Custom | โช CSS Transforms |
| Flexibility | ๐ Low (Opinionated) | ๐ High (Unopinionated) | ๐ Low (List only) |
| Modern React Ready | โ Yes | โ Yes | โ No (HOC friction) |
| Maintenance Status | ๐ถ Maintenance Mode | โ Active | โ ๏ธ Stale |
react-beautiful-dnd is the "appliance" approach. It works beautifully out of the box for standard lists and boards, enforcing best practices for accessibility and animation. Use it if you need a Trello-like board tomorrow and don't need to customize the physics. However, be aware of its maintenance status.
react-dnd is the "toolkit" approach. It gives you the raw materials to build any DnD interaction imaginable. It requires more engineering effort but pays off in flexibility and control. It is the correct choice for complex dashboards, design tools, or games.
react-sortable-hoc is the "legacy shortcut." It solves a narrow problem quickly but introduces architectural debt via HOCs. In 2024 and beyond, there is almost no reason to choose this over the other two options for new development.
Final Thought: If you are building a standard list, react-beautiful-dnd (or its successor @dnd-kit) is your fastest path to a high-quality result. If you are building a platform where DnD is a core, complex feature, react-dnd provides the architectural foundation you need. Avoid react-sortable-hoc unless you are maintaining an existing codebase that already depends on it.
Choose react-beautiful-dnd if you need a polished, accessible DnD experience for standard lists or kanban boards with minimal configuration. It is ideal for teams that want strict enforcement of accessibility standards and consistent animation behavior without managing low-level events. Note that while maintenance has slowed, it remains the standard for simple, high-quality list interactions, though migration to its successor (@dnd-kit) should be considered for new greenfield projects.
Choose react-dnd if your application requires complex, non-standard DnD interactions, such as dragging between different windows, custom touch backends, or intricate visual feedback that deviates from standard list behavior. It is the best fit for architectural scenarios where you need full control over the drag lifecycle, multiple backend support (HTML5, Touch, Test), and the ability to build custom primitives from scratch.
Avoid choosing react-sortable-hoc for new projects. Its reliance on Higher-Order Components (HOCs) creates significant friction when used with modern React Hooks and functional components. While it solves simple sorting needs quickly, the architectural debt of wrapping components and the lack of active modernization make it a poor choice compared to the flexibility of react-dnd or the accessibility of react-beautiful-dnd.
This library continues to be relied upon heavily by Atlassian products, but we are focused on other priorities right now and have no current plans for further feature development or improvements.
It will continue to be here on GitHub and we will still make critical updates (e.g. security fixes, if any) as required, but will not be actively monitoring or replying to issues and pull requests.
We recommend that you donโt raise issues or pull requests, as they will not be reviewed or actioned until further notice.
We have created a free course on egghead.io ๐ฅ to help you get started with react-beautiful-dnd as quickly as possible.
<table> reordering - table pattern<Draggable />@atlaskit/tree package<Droppable /> list can be a scroll container (without a scrollable parent) or be the child of a scroll container (that also does not have a scrollable parent)react-beautiful-dnd exists to create beautiful drag and drop for lists that anyone can use - even people who cannot see. For a good overview of the history and motivations of the project you can take a look at these external resources:
There are a lot of libraries out there that allow for drag and drop interactions within React. Most notable of these is the amazing react-dnd. It does an incredible job at providing a great set of drag and drop primitives which work especially well with the wildly inconsistent html5 drag and drop feature. react-beautiful-dnd is a higher level abstraction specifically built for lists (vertical, horizontal, movement between lists, nested lists and so on). Within that subset of functionality react-beautiful-dnd offers a powerful, natural and beautiful drag and drop experience. However, it does not provide the breadth of functionality offered by react-dnd. So react-beautiful-dnd might not be for you depending on what your use case is.
The ways in which somebody can start and control a drag

<DragDropContext /> - Wraps the part of your application you want to have drag and drop enabled for<Droppable /> - An area that can be dropped into. Contains <Draggable />s<Draggable /> - What can be dragged aroundresetServerContext() - Utility for server side rendering (SSR)<DragDropContext /> responders - onDragStart, onDragUpdate, onDragEnd and onBeforeDragStart<Draggable />sinnerRefdraggableId and droppableIdsdoctypeTypeScript and flow: type information<svg>sreact-beautiful-dnd<Draggable />s during a drag (11.x behaviour) - โ ๏ธ Advanced<Draggable /> - Using our cloning API or your own portal
ํ๊ธ/Korean
ะะฐ ััััะบะพะผ/Russian
Portuguรชs/Portuguese
ฮฮปฮปฮทฮฝฮนฮบฮฌ/Greek
ๆฅๆฌ่ช/JapaneseAlex Reardon @alexandereardon
Alex is no longer personally maintaning this project. The other wonderful maintainers are carrying this project forward.