react-native-drax
Drag‑and‑drop for React Native. Done right.
Sortable lists, grids, cross-container drag, drag handles, collision algorithms, and more. Built on Reanimated 4 with a UI-thread-first architecture for smooth 60fps interactions on iOS, Android, and Web.
npm install react-native-draxList-Agnostic Sortable
Works with FlatList, FlashList, LegendList, or any list component. One API, any renderer.
Cross-Container Drag
Move items between lists for kanban boards. Phantom slots, auto-scroll, and smooth transfers.
UI-Thread Performance
Spatial index worklet runs hit-testing on the UI thread. SharedValues split by update frequency for 60fps.
19 Callback Events
Full drag lifecycle control: drag start, enter, over, exit, end, drop, snap, monitor — and continuous callbacks.
Three Platforms
iOS, Android, and Web. New Architecture (Fabric) compatible. Built on Reanimated 4 + Gesture Handler 3.
Composable Architecture
Use DraxList for convenience, or compose useSortableList + SortableContainer + SortableItem for full control.
Three lines to drag. Five to sort.
- Basic Drag & Drop
- Sortable List
- Composable API
import { DraxProvider, DraxView } from 'react-native-drax';
function App() {
return (
<DraxProvider>
<DraxView
style={{ width: 100, height: 100, backgroundColor: 'blue' }}
onDragStart={() => console.log('dragging')}
payload="hello"
/>
<DraxView
style={{ width: 100, height: 100, backgroundColor: 'green' }}
onReceiveDragDrop={({ dragged: { payload } }) => {
console.log(`received: ${payload}`);
}}
/>
</DraxProvider>
);
}
import { useState } from 'react';
import { Text, View } from 'react-native';
import { DraxProvider, DraxList } from 'react-native-drax';
function App() {
const [items, setItems] = useState(['A', 'B', 'C', 'D', 'E']);
return (
<DraxProvider>
<DraxList
data={items}
keyExtractor={(item) => item}
onReorder={({ data }) => setItems(data)}
renderItem={({ item }) => (
<View style={{ padding: 16, backgroundColor: '#eee', margin: 4 }}>
<Text>{item}</Text>
</View>
)}
/>
</DraxProvider>
);
}
import {
DraxProvider, useSortableList,
SortableContainer, SortableItem,
} from 'react-native-drax';
import { FlatList, Text } from 'react-native';
function App() {
const [items, setItems] = useState(['A', 'B', 'C', 'D', 'E']);
const listRef = useRef<FlatList>(null);
const sortable = useSortableList({
data: items,
keyExtractor: (item) => item,
onReorder: ({ data }) => setItems(data),
});
return (
<DraxProvider>
<SortableContainer sortable={sortable} scrollRef={listRef}>
<FlatList
ref={listRef}
data={sortable.data}
keyExtractor={sortable.stableKeyExtractor}
onScroll={sortable.onScroll}
onContentSizeChange={sortable.onContentSizeChange}
renderItem={({ item, index }) => (
<SortableItem sortable={sortable} index={index}>
<Text>{item}</Text>
</SortableItem>
)}
/>
</SortableContainer>
</DraxProvider>
);
}
How Drax compares
| Feature | Drax | reanimated-dnd | sortables |
|---|---|---|---|
| Free-form drag & drop | Yes | Yes | No |
| Sortable list | Yes | Yes | Yes |
| Sortable grid | Yes | Yes | Yes |
| Cross-container drag (kanban) | Yes | No | No |
| List-agnostic | Yes | No | No |
| Drag handles | Yes | Yes | No |
| Collision algorithms | 3 modes | Yes | No |
| Drag bounds | Yes | Yes | No |
| Drop zone acceptance | Yes | No | No |
| Monitoring views | Yes | No | No |
| UI-thread hit-testing | Yes | No | No |
| Hover styles | 5 states | No | No |
| Animation presets | 5 + custom | Yes | No |
| Snap alignment | 9-point | No | No |
| Accessibility | Yes | Yes | No |
| Continuous drag callbacks | Yes | No | No |
| Reanimated version | 4 | 4 | 3 |
| Gesture Handler version | 3 (beta) | ~2.30 | 2 |
| Web support | Yes | No | No |