Claude
Skills
Sign in
Back

reanimated-dnd

Included with Lifetime
$97 forever

Integrate react-native-reanimated-dnd for drag-and-drop, sortable lists, sortable grids, and drop zones in React Native apps. Covers components, hooks, and all configuration options.

Web Dev

What this skill does


# react-native-reanimated-dnd Integration Skill

**Version:** 2.0.0
**Category:** UI / Drag and Drop
**Platform:** React Native (requires react-native-reanimated >=4.2.0, react-native-gesture-handler >=2.28.0, react-native-worklets >=0.7.0)

---

## Overview

`react-native-reanimated-dnd` provides performant drag-and-drop primitives for React Native. It offers both high-level components and low-level hooks for:

- **Drag & Drop**: Move items between drop zones
- **Sortable Lists**: Vertical and horizontal reorderable lists
- **Sortable Grids**: 2D grids with insert or swap reordering
- **Constraints**: Axis locking, bounded dragging, collision detection
- **Dynamic Heights**: Auto-measuring variable-height items in lists

All animations run on the UI thread via Reanimated worklets.

---

## Installation

```bash
npm install react-native-reanimated-dnd
# or
yarn add react-native-reanimated-dnd
```

### Peer dependencies (must be installed separately)

```bash
npm install react-native-reanimated react-native-gesture-handler react-native-worklets
```

### Required setup

Wrap your app root with `GestureHandlerRootView`:

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

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* Your app content */}
    </GestureHandlerRootView>
  );
}
```

---

## Core Architecture

```
DropProvider (context - required for Draggable/Droppable)
├── Draggable (items that can be picked up)
│   └── Draggable.Handle (optional restricted drag area)
└── Droppable (zones that accept drops)

Sortable (self-contained vertical/horizontal list)
├── SortableItem (individual reorderable item)
│   └── SortableItem.Handle (optional restricted drag area)

SortableGrid (self-contained 2D grid)
├── SortableGridItem (individual grid cell)
│   └── SortableGridItem.Handle (optional restricted drag area)
```

**Key rule**: All data items MUST have an `id: string` property for tracking.

---

## Pattern 1: Basic Drag & Drop

Use `DropProvider` + `Draggable` + `Droppable` to move items into drop zones.

```tsx
import {
  DropProvider,
  Draggable,
  Droppable,
} from 'react-native-reanimated-dnd';

function DragDropExample() {
  const [droppedItem, setDroppedItem] = useState<string | null>(null);

  return (
    <DropProvider>
      <View style={styles.items}>
        <Draggable data={{ id: '1', label: 'Item A' }}>
          <View style={styles.item}>
            <Text>Item A</Text>
          </View>
        </Draggable>

        <Draggable data={{ id: '2', label: 'Item B' }}>
          <View style={styles.item}>
            <Text>Item B</Text>
          </View>
        </Draggable>
      </View>

      <Droppable onDrop={(data) => setDroppedItem(data.label)}>
        <View style={styles.dropZone}>
          <Text>{droppedItem ?? 'Drop here'}</Text>
        </View>
      </Droppable>
    </DropProvider>
  );
}
```

### Draggable Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `TData` | required | Payload passed to drop handlers |
| `draggableId` | `string` | auto | Unique identifier |
| `dragDisabled` | `boolean` | `false` | Disable dragging |
| `preDragDelay` | `number` | `0` | Delay in ms before drag starts |
| `dragAxis` | `"x" \| "y" \| "both"` | `"both"` | Constrain movement axis |
| `dragBoundsRef` | `RefObject<View>` | - | Constrain within a view |
| `collisionAlgorithm` | `"center" \| "intersect" \| "contain"` | `"intersect"` | How to detect overlap with droppables |
| `animationFunction` | `(toValue: number) => number` | - | Custom return animation |
| `onDragStart` | `(data: TData) => void` | - | Called when drag begins |
| `onDragEnd` | `(data: TData) => void` | - | Called when drag ends |
| `onDragging` | `({ x, y, tx, ty, itemData }) => void` | - | Real-time position updates |
| `onStateChange` | `(state: DraggableState) => void` | - | State transition callback |

### Droppable Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `onDrop` | `(data: TData) => void` | required | Handle dropped items |
| `dropDisabled` | `boolean` | `false` | Disable dropping |
| `capacity` | `number` | `1` | Max items allowed |
| `dropAlignment` | `DropAlignment` | `"center"` | Position alignment for dropped items |
| `dropOffset` | `{ x: number, y: number }` | - | Fine-tune position after alignment |
| `activeStyle` | `StyleProp<ViewStyle>` | - | Style applied when item hovers over |
| `onActiveChange` | `(isActive: boolean) => void` | - | Called when hover state changes |
| `droppableId` | `string` | auto | Unique identifier for the drop zone |

### DropProvider Props

| Prop | Type | Description |
|------|------|-------------|
| `onDroppedItemsUpdate` | `(items: DroppedItemsMap) => void` | Track items across all zones |
| `onDragging` | `({ x, y, tx, ty, itemData }) => void` | Global drag position tracking |
| `onDragStart` | `(data) => void` | Any drag begins |
| `onDragEnd` | `(data) => void` | Any drag ends |
| `onLayoutUpdateComplete` | `() => void` | Called when layout updates finish |

### DropAlignment values
`"center"` | `"top-left"` | `"top-center"` | `"top-right"` | `"center-left"` | `"center-right"` | `"bottom-left"` | `"bottom-center"` | `"bottom-right"`

---

## Pattern 2: Drag Handles

Restrict the draggable area to a specific handle region using `Draggable.Handle`:

```tsx
<Draggable data={{ id: '1', label: 'Card' }}>
  <View style={styles.card}>
    <Draggable.Handle>
      <View style={styles.handleBar}>
        <Text>Drag here</Text>
      </View>
    </Draggable.Handle>
    <View style={styles.cardContent}>
      <Text>This area does NOT initiate drag</Text>
    </View>
  </View>
</Draggable>
```

The same pattern works for sortable items with `SortableItem.Handle`.

---

## Pattern 3: Vertical Sortable List

Use the `Sortable` component for a reorderable list:

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

interface Item {
  id: string;
  title: string;
}

const ITEM_HEIGHT = 60;

function SortableListExample() {
  const [items, setItems] = useState<Item[]>([
    { id: '1', title: 'First' },
    { id: '2', title: 'Second' },
    { id: '3', title: 'Third' },
  ]);

  const renderItem = useCallback(({ item, ...props }) => (
    <SortableItem
      key={item.id}
      id={item.id}
      data={item}
      onMove={(id, from, to) => {
        setItems(prev => {
          const next = [...prev];
          const [moved] = next.splice(from, 1);
          next.splice(to, 0, moved);
          return next;
        });
      }}
      {...props}
    >
      <View style={styles.listItem}>
        <Text>{item.title}</Text>
      </View>
    </SortableItem>
  ), []);

  return (
    <Sortable
      data={items}
      renderItem={renderItem}
      itemHeight={ITEM_HEIGHT}
    />
  );
}
```

### Sortable Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `TData[]` | required | Items (each must have `id: string`) |
| `renderItem` | `(props) => ReactNode` | required | Item renderer |
| `direction` | `"vertical" \| "horizontal"` | `"vertical"` | List direction |
| `itemHeight` | `number \| number[] \| (item, i) => number` | - | Item height (required for vertical) |
| `itemWidth` | `number` | - | Item width (required for horizontal) |
| `gap` | `number` | `0` | Gap between items (horizontal only) |
| `paddingHorizontal` | `number` | `0` | Container padding (horizontal only) |
| `enableDynamicHeights` | `boolean` | `false` | Auto-measure item heights |
| `estimatedItemHeight` | `number` | `60` | Fallback height for unmeasured items |
| `onHeightsMeasured` | `(heights) => void` | - | Called with measured heights |
| `useFlatList` | `boolean` | `true` | Use FlatList for virtualization |
| `itemKeyExtractor` | `(item, index) => string` | `item.id` | Custom key extraction function |
| `style` | `StyleProp<ViewStyle>` | 

Related in Web Dev