facilitron-sortable-list
v1.0.4
Published
A performant, flicker-free sortable list component for React Native with drag-and-drop reordering
Maintainers
Readme
facilitron-sortable-list
⚠️ DEPRECATED: This package has been renamed to
react-native-sortable-drag-list. Please update your dependencies to use the new package name.
A performant, flicker-free sortable list component for React Native with drag-and-drop reordering capabilities.
Features
- 🚀 Flicker-free reordering - Smooth animations with no visual glitches
- 📱 Native performance - Built with React Native Reanimated 2 and Gesture Handler
- 🎯 Precise drag detection - Long press to activate, smooth gesture handling
- 📍 Scroll position preservation - Maintains scroll position during reordering
- 🔄 State persistence - Survives component remounts and updates
- 🎨 Customizable rendering - Flexible item rendering with active state support
- 📏 Configurable item height - Consistent item heights for optimal performance
Installation
⚠️ Please use the new package name:
yarn add react-native-sortable-drag-list
# or
npm install react-native-sortable-drag-listLegacy package (deprecated):
yarn add facilitron-sortable-list
# or
npm install facilitron-sortable-listPeer Dependencies
This library requires the following peer dependencies:
yarn add react-native-reanimated react-native-gesture-handler
# or
npm install react-native-reanimated react-native-gesture-handlerUsage
import React, { useState } from 'react';
import { View, Text } from 'react-native';
import { SortableList } from 'react-native-sortable-drag-list';
interface Item {
id: string;
title: string;
}
const MyComponent = () => {
const [items, setItems] = useState<Item[]>([
{ id: '1', title: 'Item 1' },
{ id: '2', title: 'Item 2' },
{ id: '3', title: 'Item 3' },
]);
const renderItem = ({
item,
isActive,
}: {
item: Item;
isActive: boolean;
}) => (
<View style={[styles.item, isActive && styles.activeItem]}>
<Text>{item.title}</Text>
</View>
);
return (
<SortableList
data={items}
keyExtractor={(item) => item.id}
renderItem={renderItem}
itemHeight={70} // Optional: customize item height
onOrderChange={(newOrder) => {
const reorderedItems = newOrder.map((index) => items[index]);
setItems(reorderedItems);
}}
/>
);
};API Reference
SortableList Props
| Prop | Type | Required | Description |
| --------------- | -------------------------------------------------------- | -------- | --------------------------------- |
| data | T[] | ✅ | Array of items to render |
| keyExtractor | (item: T, index: number) => string | ✅ | Function to extract unique keys |
| renderItem | (args: { item: T; isActive: boolean }) => ReactElement | ✅ | Function to render each item |
| onDragEnd | () => void | ❌ | Callback when drag operation ends |
| onOrderChange | (newOrder: number[]) => void | ❌ | Callback when order changes |
| itemHeight | number | ❌ | Height of each item (default: 70) |
SortableItem Props
| Prop | Type | Required | Description |
| ------------- | ---------------------------------------------------------- | -------- | --------------------------------- |
| item | T | ✅ | The item data |
| index | number | ✅ | Visual index in the list |
| dataLength | number | ✅ | Total number of items |
| renderItem | (params: { item: T; isActive: boolean }) => ReactElement | ✅ | Item renderer |
| activeIndex | SharedValue<number> | ✅ | Currently active item index |
| fromSlot | SharedValue<number> | ✅ | Starting position of dragged item |
| targetSlot | SharedValue<number> | ✅ | Target position of dragged item |
| onDragStart | () => void | ✅ | Drag start callback |
| onDragEnd | (payload: { from: number; to: number }) => void | ✅ | Drag end callback |
Advanced Usage
Custom Item Height
// Pass custom item height directly to SortableList
<SortableList
data={items}
keyExtractor={(item) => item.id}
renderItem={renderItem}
itemHeight={100} // Custom height instead of default 70
onOrderChange={(newOrder) => {
const reorderedItems = newOrder.map((index) => items[index]);
setItems(reorderedItems);
}}
/>Handling Scroll Position
const MyComponent = () => {
const [items, setItems] = useState(/* ... */);
return (
<SortableList
data={items}
keyExtractor={(item) => item.id}
renderItem={renderItem}
onOrderChange={(newOrder) => {
// The component automatically preserves scroll position
// during reordering operations
setItems(newOrder.map((index) => items[index]));
}}
onDragEnd={() => {
// Optional: Perform actions when drag ends
console.log('Drag operation completed');
}}
/>
);
};Custom Item Rendering with Active State
import { View, Text } from 'react-native';
import Animated from 'react-native-reanimated';
const renderItem = ({ item, isActive }: { item: Item; isActive: boolean }) => (
<Animated.View
style={[
styles.item,
isActive && styles.activeItem,
// Add custom animations based on isActive
]}
>
<Text style={styles.title}>{item.title}</Text>
{isActive && <Text style={styles.draggingLabel}>Dragging...</Text>}
</Animated.View>
);Performance Features
- Hardware acceleration - Uses
renderToHardwareTextureAndroidfor smooth animations - Offscreen compositing - Prevents visual artifacts during complex animations
- Stable keys - Maintains React reconciliation efficiency
- Shared values - Efficient state management with Reanimated
- Gesture optimization - Minimal gesture detection overhead
Browser Support
This library is designed for React Native and does not support web browsers.
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
1.0.0
- Initial release
- Flicker-free drag and drop reordering
- Scroll position preservation
- State persistence across remounts
- Hardware acceleration support
