A powerful drag-and-drop library for React Native using Reanimated 3
npm install react-native-reanimated-dnd
_Powerful, performant, and built for the modern React Native developer_




---
After countless attempts with drag-and-drop solutions that don't work or are simply outdated, this is something that _finally_ works. And it is not just another DnD library, but a complete ecosystem built from the ground up for React Native, offering a best-in-class developer experience and production-ready performance.
Highly feature-packed with every interaction pattern you'll ever need, yet simple enough to get started in minutes. Built for developers who demand both power and simplicity.
- ๐ High Performance - Built with Reanimated 3 for buttery-smooth 60fps animations
- ๐๏ธ Full RN Fabric Support - Works seamlessly with both New Architecture and Old Architecture
- ๐ฆ Expo Compatible - Zero configuration needed, works out of the box with Expo
- ๐ชถ Tiny Bundle Size - Only 70kb unpacked size, won't bloat your app
- ๐ฏ Flexible API - From simple drag-and-drop to complex sortable lists
- ๐ฑ React Native First - Designed specifically for mobile, not ported from web
- ๐ง TypeScript Ready - Full type safety with comprehensive definitions
- ๐จ Infinitely Customizable - Every animation, behavior, and style is configurable
- ๐ฆ Complete Component Suite - Draggable, Droppable, Sortable, and more
- ๐ช Smart Collision Detection - Multiple algorithms (center, intersect, contain)
- ๐ Sortable Lists - Drag and drop to sort a Vertical List, also
supports Automatic scrolling for out of screen dragging
- ๐ญ Drag Handles - Precise control with dedicated drag areas
- ๐ฌ Custom Animations - Spring, timing, or bring your own animation functions
- ๐ Pixel-Perfect Positioning - 9-point alignment system with custom offsets
- ๐ฆ Boundary Constraints - Keep draggables within specific areas
- โก State Management - Complete lifecycle tracking and callbacks
- ๐ฏ Developer Experience - Intuitive APIs, helpful warnings, and extensive examples
See it in action! A comprehensive example app with 15 interactive demos showcasing every feature and use case.
๐ฑ Scan & Play _Scan with your camera or Expo Go app_ | ๐ Quick Start 1. Install Expo Go on your phone Or browse the code: |
_Comprehensive guides, API reference, and interactive examples_
The example app includes:
- ๐ต Sortable Music Queue - Complete list reordering with handles
- ๐ฏ Collision Detection - Different algorithms in action
- ๐ฌ Custom Animations - Spring, timing, and easing variations
- ๐ฆ Boundary Constraints - Axis-locked and bounded dragging
- โจ Visual Feedback - Active styles and state management
- โ๏ธ Advanced Patterns - Custom implementations and hooks
See the library in action with these demos showcasing some of the key features and use cases.
$3_Drag and drop to reorder items with smooth animations_ https://github.com/user-attachments/assets/1cd1929c-724b-4dda-a916-f3e69f917f7b Features: Auto-scrolling โข Drag handles โข Smooth transitions | $3_Multiple algorithms for precise drop targeting_ https://github.com/user-attachments/assets/379040d7-8489-430b-bae4-3fcbde34264e Algorithms: Center โข Intersect โข Contain |
$3_Precise control with dedicated drag areas_ https://github.com/user-attachments/assets/ec051d5b-8ba0-41b7-86ae-379de26a97dd Features: Touch-friendly โข Visual feedback โข Accessibility | $3_Constrain movement within specific boundaries_ https://github.com/user-attachments/assets/7bd5045b-47c4-4d9b-a0c5-eb89122ec9c0 Constraints: Axis-locked โข Container bounds โข Custom limits |
$3_Visual feedback during drag operations_ https://github.com/user-attachments/assets/3b8a3d00-38ad-4532-bd42-173037ea61b9 Feedback: Hover states โข Drop zones โข Visual cues | $3_Complete lifecycle tracking and callbacks_ https://github.com/user-attachments/assets/da5e526f-f2d2-4dc5-96b5-3fecc4faf57a States: Idle โข Dragging โข Animating โข Dropped |
``bash`
npm install react-native-reanimated-dnd
`bash`
npm install react-native-reanimated react-native-gesture-handler
Follow the setup guides:
- React Native Reanimated
- React Native Gesture Handler
`tsx
import React from "react";
import { View, Text, StyleSheet } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Draggable, DropProvider } from "react-native-reanimated-dnd";
export default function App() {
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#000000",
},
content: {
flex: 1,
padding: 20,
justifyContent: "center",
alignItems: "center",
},
draggableItem: {
padding: 20,
backgroundColor: "#1C1C1E",
borderRadius: 12,
borderWidth: 1,
borderColor: "#3A3A3C",
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 3,
},
itemText: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "600",
textAlign: "center",
},
});
`
`tsx
import React from "react";
import { Alert, StyleSheet, Text, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import {
Draggable,
Droppable,
DropProvider,
} from "react-native-reanimated-dnd";
export default function DragDropExample() {
const handleDrop = (data: any, zoneId: string) => {
Alert.alert("Item Dropped", "${data.title}" dropped in ${zoneId});
};
return (
{/ Drop Zones /}
activeStyle={styles.dropZoneActive}
style={styles.droppable}
>
activeStyle={styles.dropZoneActive}
style={styles.droppable}
>
{/ Draggable Item /}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#000000",
},
content: {
flex: 1,
padding: 20,
justifyContent: "space-between",
},
sectionTitle: {
color: "#FFFFFF",
fontSize: 18,
fontWeight: "700",
marginBottom: 20,
textAlign: "center",
},
draggableSection: {
alignItems: "center",
paddingVertical: 40,
},
draggableItem: {
padding: 20,
backgroundColor: "#1C1C1E",
borderRadius: 12,
borderWidth: 1,
borderColor: "#3A3A3C",
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 3,
},
itemText: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "600",
textAlign: "center",
},
dropZonesSection: {
flex: 1,
paddingVertical: 40,
},
droppable: {
marginBottom: 20,
overflow: "hidden",
borderRadius: 16,
},
dropZone: {
height: 140,
borderWidth: 2,
borderStyle: "dashed",
borderRadius: 16,
justifyContent: "center",
alignItems: "center",
padding: 20,
},
dropZoneBlue: {
borderColor: "#58a6ff",
backgroundColor: "rgba(88, 166, 255, 0.08)",
},
dropZoneGreen: {
borderColor: "#3fb950",
backgroundColor: "rgba(63, 185, 80, 0.08)",
},
dropZoneActive: {
backgroundColor: "rgba(255, 255, 255, 0.1)",
borderStyle: "solid",
transform: [{ scale: 1.02 }],
},
dropZoneText: {
color: "#FFFFFF",
fontSize: 18,
fontWeight: "600",
textAlign: "center",
marginBottom: 8,
},
dropZoneSubtext: {
color: "#8E8E93",
fontSize: 14,
textAlign: "center",
},
});
`
`tsx
import React, { useCallback, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import {
Sortable,
SortableItem,
SortableRenderItemProps,
} from "react-native-reanimated-dnd";
interface Task {
id: string;
title: string;
completed: boolean;
}
export default function SortableExample() {
const [tasks, setTasks] = useState
{ id: "1", title: "Learn React Native", completed: false },
{ id: "2", title: "Build an app", completed: false },
{ id: "3", title: "Deploy to store", completed: true },
{ id: "4", title: "Celebrate success", completed: false },
]);
const renderTask = useCallback(
(props: SortableRenderItemProps
const {
item,
id,
positions,
lowerBound,
autoScrollDirection,
itemsCount,
itemHeight,
} = props;
return (
data={item}
id={id}
positions={positions}
lowerBound={lowerBound}
autoScrollDirection={autoScrollDirection}
itemsCount={itemsCount}
itemHeight={itemHeight}
onMove={(itemId, from, to) => {
const newTasks = [...tasks];
const [movedTask] = newTasks.splice(from, 1);
newTasks.splice(to, 0, movedTask);
setTasks(newTasks);
}}
style={styles.taskItem}
>
{item.completed ? "โ
Completed" : "โณ Pending"}
{/ Drag Handle /}
);
},
[tasks]
);
return (
renderItem={renderTask}
itemHeight={80}
style={styles.list}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#000000",
},
header: {
padding: 20,
paddingBottom: 16,
borderBottomWidth: 1,
borderBottomColor: "#2C2C2E",
},
headerTitle: {
color: "#FFFFFF",
fontSize: 24,
fontWeight: "700",
marginBottom: 4,
},
headerSubtitle: {
color: "#8E8E93",
fontSize: 14,
},
list: {
flex: 1,
backgroundColor: "#000000",
marginTop: 20,
paddingHorizontal: 20,
borderRadius: 20,
overflow: "hidden",
},
taskItem: {
height: 80,
backgroundColor: "transparent",
},
taskContent: {
flex: 1,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 20,
backgroundColor: "#1C1C1E",
borderWidth: 1,
borderColor: "#3A3A3C",
},
taskInfo: {
flex: 1,
paddingRight: 16,
},
taskTitle: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "600",
marginBottom: 4,
},
taskStatus: {
color: "#8E8E93",
fontSize: 14,
},
dragHandle: {
padding: 12,
borderRadius: 8,
backgroundColor: "rgba(255, 255, 255, 0.05)",
},
dragIconContainer: {
flexDirection: "row",
alignItems: "center",
gap: 3,
},
dragColumn: {
flexDirection: "column",
gap: 2,
},
dragDot: {
width: 3,
height: 3,
borderRadius: 1.5,
backgroundColor: "#6D6D70",
},
});
`
####
Makes any component draggable with extensive customization options.
`tsx`
onDragStart={(data) => void} // Called when dragging starts
onDragEnd={(data) => void} // Called when dragging ends
onDragging={(position) => void} // Called during dragging
onStateChange={(state) => void} // Called on state changes
dragDisabled={boolean} // Disable dragging
collisionAlgorithm="center|intersect|contain" // Collision detection method
dragAxis="x|y|both" // Constrain movement axis
dragBoundsRef={RefObject} // Boundary container reference
animationFunction={(toValue) => Animation} // Custom animation function
style={StyleProp
>
{children}
####
Creates drop zones with visual feedback and capacity management.
`tsx`
onActiveChange={(isActive) => void} // Called on hover state change
dropDisabled={boolean} // Disable drop functionality
dropAlignment="top-left|center|bottom-right|..." // Drop positioning
dropOffset={{ x: number, y: number }} // Position offset
activeStyle={StyleProp
capacity={number} // Maximum items allowed
droppableId={string} // Unique identifier
>
{children}
####
High-level component for sortable lists with auto-scrolling.
`tsx`
renderItem={(props) => ReactNode} // Render function for items
itemHeight={number} // Height of each item
itemKeyExtractor={(item) => string} // Custom key extractor
style={StyleProp
contentContainerStyle={StyleProp
/>
####
Individual item within a sortable list with gesture handling.
`tsx`
data={any} // Item data
positions={SharedValue} // Position tracking
onMove={(id, from, to) => void} // Called when item moves
onDragStart={(id, position) => void} // Called when dragging starts
onDrop={(id, position) => void} // Called when item is dropped
onDragging={(id, overItemId, y) => void} // Called during dragging
style={StyleProp
animatedStyle={StyleProp
>
{children}
#### useDraggable(options)
Core hook for implementing draggable functionality.
#### useDroppable(options)
Core hook for implementing droppable functionality.
#### useSortable(options)
Hook for individual sortable items with position management.
#### useSortableList(options)
Hook for managing entire sortable lists with auto-scrolling.
####
Required context provider that manages global drag-and-drop state.
`tsx`
#### DraggableState
`tsx`
enum DraggableState {
IDLE = "idle",
DRAGGING = "dragging",
ANIMATING = "animating",
}
#### CollisionAlgorithm
`tsx`
type CollisionAlgorithm = "center" | "intersect" | "contain";
#### DropAlignment
`tsx`
type DropAlignment =
| "top-left"
| "top-center"
| "top-right"
| "center-left"
| "center"
| "center-right"
| "bottom-left"
| "bottom-center"
| "bottom-right";
`tsx
import { withTiming, withSpring, Easing } from "react-native-reanimated";
// Smooth timing animation
const smoothAnimation = (toValue) => {
"worklet";
return withTiming(toValue, {
duration: 300,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
});
};
// Spring animation
const springAnimation = (toValue) => {
"worklet";
return withSpring(toValue, {
damping: 15,
stiffness: 150,
});
};
`
`tsx
// Precise center-point collision
{/ Requires center point to be over drop zone /}
// Forgiving intersection collision (default)
{/ Any overlap triggers collision /}
// Strict containment collision
{/ Entire draggable must be within drop zone /}
`
`tsx
{/ Only this handle area can initiate dragging /}
`
`tsx
const containerRef = useRef
dragBoundsRef={containerRef}
dragAxis="x" // Constrain to horizontal movement
>
{/ content /}
`
`tsx`
onDrop={(data) => {
if (currentItems.length < 3) {
addItem(data);
}
}}
activeStyle={{
backgroundColor: currentItems.length < 3 ? "#e8f5e8" : "#ffe8e8",
}}
>
1. Clone the repository:
`bash`
git clone https://github.com/entropyconquers/react-native-reanimated-dnd.git
cd react-native-reanimated-dnd
2. Install dependencies:
`bash`
npm install
cd example-app
npm install
3. Run the example app:
`bashiOS
npx expo run:ios
The example app includes all 15 interactive examples showcasing every feature of the library.
I am constantly working to improve React Native Reanimated DnD. Here's what's coming next:
Focus: Enhanced Functionality & Bug Fixes
- ๐ Bug Fixes & Issues Resolution
- Address existing reported issues
- Performance optimizations
- Gesture handling improvements
- API Improvements
- ๐ Sortable Grids
- 2D grid drag-and-drop support
- Flexible grid layouts (2x2, 3x3, custom)
- Smart auto-positioning and gap management
- Responsive grid behavior
- โ๏ธ Horizontal Sortable Lists
- Full horizontal scrolling support
- Auto-scroll for out-of-view items
- Customizable scroll behavior
- ๐ช Nested Sortable Lists
- Multi-level hierarchy support
- Collapse/expand functionality
- Parent-child relationship management
- Tree-like data structure handling
- ๐ Kanban Board Support
- Cross-list dragging capabilities
- Multiple column support
- Inter-list item transfer
- Board-level state management
Vote on features you'd like to see by raising an issue.
Have an idea? Open a feature request and let me know!
Contributions are always welcome! We believe in building this library together with the community.
Ways to contribute:
- ๐ Report bugs and issues
- โจ Suggest new features
- ๐ง Submit pull requests
- ๐ Improve documentation
- ๐งช Write tests
- ๐ฌ Help others in discussions
Please see our Contributing Guide for detailed information on:
- Setting up the development environment
- Code style guidelines
- Pull request process
- Testing requirements
- Community guidelines
MIT ยฉ Vishesh Raheja
- Built with React Native Reanimated for smooth 60fps animations
- Gesture handling powered by React Native Gesture Handler
- Inspired by the React ecosystem's drag-and-drop libraries
- Special thanks to the React Native community for feedback and contributions