Skip to main content

Basic Concepts

Understanding the core concepts and architecture of React Native Reanimated DnD.

Architecture Overview

The library is built around a context-based architecture that enables seamless communication between draggable and droppable components.

Core Components

App
├── GestureHandlerRootView (Required)
└── DropProvider (Context)
├── Draggable (Items that can be moved)
├── Droppable (Areas where items can be dropped)
└── Sortable (Special case for reorderable lists)
└── SortableItem (Individual items in sortable lists)

Component Hierarchy

  1. GestureHandlerRootView: Required wrapper for gesture handling
  2. DropProvider: Creates the drag-and-drop context
  3. Draggable/Droppable: Core interaction components
  4. Sortable/SortableItem: Higher-level components for lists

Core Concepts

1. Context-Based Communication

All drag-and-drop functionality relies on React Context for component communication:

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { DropProvider } from 'react-native-reanimated-dnd';

// The DropProvider creates a context that enables:
// - Registration of draggable and droppable components
// - Collision detection between components
// - State management for active drags
// - Position tracking and updates

function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<DropProvider>
{/* All drag-and-drop components must be children of DropProvider */}
<YourComponents />
</DropProvider>
</GestureHandlerRootView>
);
}

2. Data-Driven Interactions

Every draggable component carries data that flows through the drag-and-drop system:

// Data flows from draggable to droppable
<Draggable data={{ id: '1', name: 'Task 1', priority: 'high' }}>
<Text>Drag me!</Text>
</Draggable>

<Droppable onDrop={(data) => {
// Receives: { id: '1', name: 'Task 1', priority: 'high' }
console.log('Received:', data);
}}>
<Text>Drop zone</Text>
</Droppable>

3. Collision Detection

The library automatically handles collision detection between draggable items and drop zones:

// Different collision algorithms available:
<Draggable
data={data}
collisionAlgorithm="intersect" // Default - any overlap
>
<Text>Easy to drop</Text>
</Draggable>

<Draggable
data={data}
collisionAlgorithm="center" // Center point must be over droppable
>
<Text>Precise dropping</Text>
</Draggable>

<Draggable
data={data}
collisionAlgorithm="contain" // Entire item must be contained
>
<Text>Strict containment</Text>
</Draggable>

4. Animation System

Built on React Native Reanimated for smooth, performant animations:

// Automatic spring animations on drop
<Draggable
data={data}
animationFunction={(toValue) => {
'worklet';
return withSpring(toValue, {
damping: 15,
stiffness: 150
});
}}
>
<Text>Custom animation</Text>
</Draggable>

Component Types

Draggable Components

Make any React Native component draggable:

import { Draggable } from 'react-native-reanimated-dnd';

function TaskItem({ task }) {
return (
<Draggable data={task}>
<View style={styles.taskCard}>
<Text>{task.title}</Text>
<Text>Priority: {task.priority}</Text>
</View>
</Draggable>
);
}

Key Features:

  • Automatic gesture handling
  • Collision detection
  • Animation support
  • Boundary constraints
  • Axis restrictions
  • Handle-based dragging

Droppable Components

Create areas where draggable items can be dropped:

import { Droppable } from 'react-native-reanimated-dnd';

function DropZone({ onTaskDrop }) {
return (
<Droppable
onDrop={onTaskDrop}
dropAlignment="center"
capacity={5}
>
<View style={styles.dropZone}>
<Text>Drop tasks here</Text>
</View>
</Droppable>
);
}

Key Features:

  • Drop event handling
  • Visual feedback for active drops
  • Alignment options for dropped items
  • Capacity limits
  • Custom styling for different states

Sortable Components

High-level components for reorderable lists:

import { Sortable, SortableItem } from 'react-native-reanimated-dnd';
import { useCallback } from 'react';

function TaskList({ tasks, onTaskReorder }) {
const renderTask = useCallback(({ item, id, positions, ...props }) => (
<SortableItem
key={id}
id={id}
positions={positions}
{...props}
onMove={(itemId, from, to) => {
// Update task order when items are moved
const newTasks = [...tasks];
const [movedTask] = newTasks.splice(from, 1);
newTasks.splice(to, 0, movedTask);
onTaskReorder(newTasks);
}}
>
<TaskCard task={item} />
</SortableItem>
), [tasks, onTaskReorder]);

return (
<Sortable
data={tasks}
renderItem={renderTask}
itemHeight={60}
/>
);
}

Key Features:

  • Automatic list reordering
  • Smooth item animations
  • Handle-based sorting
  • Custom item heights
  • Performance optimization for large lists

DropProvider

The DropProvider creates a context that enables:

  • Component Registration: Draggable and droppable components register themselves
  • Collision Detection: Automatic detection of overlaps between components
  • State Management: Tracking of active drags and dropped items
  • Position Updates: Handling layout changes and position recalculations
  • Event Coordination: Global callbacks for drag events

Provider Configuration

import { GestureHandlerRootView } from 'react-native-gesture-handler';

<GestureHandlerRootView style={{ flex: 1 }}>
<DropProvider
onDragStart={(data) => console.log('Drag started:', data)}
onDragEnd={(data) => console.log('Drag ended:', data)}
onDroppedItemsUpdate={(items) => console.log('Items updated:', items)}
onDragging={({ x, y, tx, ty, itemData }) => {
console.log(`${itemData.name} at (${x + tx}, ${y + ty})`);
}}
>
<YourApp />
</DropProvider>
</GestureHandlerRootView>

Data Flow

1. Registration Phase

When components mount, they register with the DropProvider:

// Draggable registers itself with unique ID and data
<Draggable data={{ id: '1', name: 'Item 1' }}>
{/* Component registers on mount */}
</Draggable>

// Droppable registers itself with position and drop handler
<Droppable onDrop={handleDrop}>
{/* Component registers on mount */}
</Droppable>

2. Drag Initiation

When a drag starts:

  1. Gesture system detects pan gesture
  2. Draggable component becomes active
  3. Position tracking begins
  4. Global onDragStart callback fires

3. Collision Detection

During dragging:

  1. Real-time position updates
  2. Collision algorithm checks overlaps
  3. Visual feedback for valid drop zones
  4. Global onDragging callback fires

4. Drop Resolution

When drag ends:

  1. Check for valid drop target
  2. Execute drop handler if valid
  3. Animate item to final position
  4. Update dropped items registry
  5. Global onDragEnd callback fires

State Management

Internal State

The DropProvider manages several pieces of internal state:

  • Active Hover Slot: Currently hovered drop zone
  • Dropped Items Map: Registry of successfully dropped items
  • Position Update Listeners: Components that need position updates

External State Integration

Integrate with your app's state management:

function App() {
const [tasks, setTasks] = useState(initialTasks);
const [droppedItems, setDroppedItems] = useState({});

const handleDroppedItemsUpdate = (items) => {
setDroppedItems(items);

// Sync with your state management
const updatedTasks = syncTasksWithDroppedItems(tasks, items);
setTasks(updatedTasks);

// Persist to backend
saveTasks(updatedTasks);
};

return (
<GestureHandlerRootView style={{ flex: 1 }}>
<DropProvider onDroppedItemsUpdate={handleDroppedItemsUpdate}>
<TaskBoard tasks={tasks} />
</DropProvider>
</GestureHandlerRootView>
);
}

Performance Considerations

Automatic Optimizations

The library includes several automatic optimizations:

  • Memoized Context Values: Prevents unnecessary re-renders
  • Throttled Position Updates: Maintains 60fps during drags
  • Efficient Collision Detection: Optimized algorithms for different use cases
  • Automatic Cleanup: Components clean up on unmount

Manual Optimizations

You can further optimize performance:

// Use React.memo for expensive components
const ExpensiveTaskCard = React.memo(({ task }) => {
return (
<Draggable data={task}>
<ComplexTaskVisualization task={task} />
</Draggable>
);
});

// Use useCallback for event handlers
const handleDrop = useCallback((data) => {
updateTasks(data);
}, []);

// Throttle expensive operations in drag callbacks
const handleDragging = useCallback(
throttle(({ itemData, tx, ty }) => {
updateExpensiveVisualization(itemData, tx, ty);
}, 16), // 60fps
[]
);

Error Handling

Built-in Error Handling

The library includes automatic error handling:

  • Context validation (components must be within DropProvider)
  • Type checking with TypeScript
  • Graceful degradation for missing props
  • Development-time warnings for common mistakes

Custom Error Handling

Add your own error boundaries:

function DragDropErrorBoundary({ children }) {
return (
<ErrorBoundary
fallback={<Text>Drag and drop temporarily unavailable</Text>}
onError={(error) => {
console.error('Drag and drop error:', error);
analytics.track('dnd_error', { error: error.message });
}}
>
{children}
</ErrorBoundary>
);
}

function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<DragDropErrorBoundary>
<DropProvider>
<YourApp />
</DropProvider>
</DragDropErrorBoundary>
</GestureHandlerRootView>
);
}

TypeScript Support

The library is fully typed with comprehensive TypeScript support:

interface TaskData {
id: string;
title: string;
priority: 'low' | 'medium' | 'high';
}

// Typed draggable
<Draggable<TaskData> data={task}>
<TaskCard task={task} />
</Draggable>

// Typed droppable
<Droppable<TaskData> onDrop={(data: TaskData) => {
// data is properly typed
console.log(`Dropped: ${data.title}`);
}}>
<DropZone />
</Droppable>

// Typed provider callbacks
<DropProvider
onDragStart={(data: TaskData) => {
console.log(`Started dragging: ${data.title}`);
}}
onDroppedItemsUpdate={(items: DroppedItemsMap<TaskData>) => {
// items is properly typed
updateTaskState(items);
}}
>
<TaskBoard />
</DropProvider>

Next Steps

Now that you understand the basic concepts:

  1. Quick Start - Build your first drag-and-drop interface
  2. Setup Provider - Learn advanced provider configuration
  3. API Reference - Explore all available components and hooks
  4. Examples - See real-world implementations
  5. Performance Guide - Optimize your implementation