react-native-drag-n-drop-everywhere v1.4.8
react-native-drag-n-drop-everywhere
A scrollable React Native drag-and-drop library that doesn't use FlatList, which can sometimes cause re-render issues. Designed to work on Web, iOS, and Android.
Built with react-native-reanimated
and react-native-gesture-handler
. Supports custom item rendering, grips for drag initiation, and more.
Web Preview | iOS Preview | Android Preview |
---|---|---|
Live Demo
Installation
npm install react-native-drag-n-drop-everywhere
Ensure you have installed and configured the following:
react-native-reanimated
react-native-gesture-handler
- (Optional) For haptic feedback on iOS:
expo-haptics
For setup instructions, refer to their documentation:
Usage
import { Platform, Text, View } from 'react-native';
import DragList from 'react-native-drag-n-drop-everywhere';
import { runOnJS } from 'react-native-reanimated';
import * as Haptics from 'expo-haptics';
const MyDragList = () => {
const dataIDsArray = [
"95a6885b-64ab-468c-9334-62c4095df459",
"b592f039-b4d6-420a-b731-0964172ed142",
"dba923d8-6743-47ab-8923-8e45eacdb204",
];
const data = {
"95a6885b-64ab-468c-9334-62c4095df459":
{ title: 'Entertainment', type: "CATEGORY_TYPE_EXPENSES" },
"b592f039-b4d6-420a-b731-0964172ed142":
{ title: 'Groceries', type: "CATEGORY_TYPE_EXPENSES" },
"dba923d8-6743-47ab-8923-8e45eacdb204":
{ title: 'Sport', type: "CATEGORY_TYPE_EXPENSES" },
};
const renderItem = ({ item }) => (
<View style={{ paddingHorizontal: 20 }}>
<Text>{data[item].title}</Text>
<Text>{data[item].type}</Text>
</View>
);
const renderGrip = () => (
<Text style={{ fontSize: 30, lineHeight: 30, fontWeight: "600" }}>:::</Text>
);
const onUpdateCallback = (newSortedData) => {
// Do not change dataIDsArray directly in useState. It will cause two-way binding and extra re-renders.
// Instead, dispatch this value
console.log(newSortedData);
};
return (
<DragList
dataIDs={dataIDsArray} // Array of IDs, required
renderItem={renderItem} // Required
callbackNewDataIds={onUpdateCallback} // Required, callback for sorted result (dataIDs)
renderGrip={renderGrip}
style={{ paddingTop: 100 }}
contentContainerStyle={{ paddingHorizontal: 10 }}
itemContainerStyle={{ borderWidth: 2 }}
itemsGap={10}
itemHeight={60}
itemBorderRadius={8}
backgroundOnHold={"#f0f0f0"}
passVibration={() => {
if (Platform.OS === 'ios') {
runOnJS(Haptics.impactAsync)(
Haptics.ImpactFeedbackStyle.Medium
);
}
}}
/>
);
};
Preventing Extra Re-renders (Optional)
If you're using global state (e.g., Redux) to store arrayIDs
and update them in callbackNewDataIds
, and you want to prevent extra re-renders of your DragList
component, use this approach in the parent component:
import { useStore } from 'react-redux';
import { useState } from 'react';
import { useFocusEffect } from '@react-navigation/native'
const ParentComponent = () => {
const store = useStore();
const [items, setItems] = useState(null);
useFocusEffect(() => { // or, useEffect if you don't want to focus it onGoback / etc
const state = store.getState();
const itemsIDs = state.categories.itemsIds; // your itemsIds in state
setItems(itemsIDs.slice()); // slice to avoid direct reference
});
if (!items) return null;
return (
// Your parent component JSX
);
};
Props
Prop | Type | Default | Required | Description |
---|---|---|---|---|
dataIDs | Array | [] | Yes | An array of unique identifiers corresponding to each list item. |
renderItem | Function | - | Yes | Function to render each list item. Receives { item } as its first argument. |
callbackNewDataIds | Function | - | Yes | Callback that receives changes (sorted array of dataIDs). Note: do not change the provided dataIDs array directly in state, as it will cause two-way binding and extra re-renders. |
renderGrip | Function | null | No | Optional function to render a grip for dragging. |
itemsGap | Number | 5 | No | The space (in pixels) between each list item. |
itemHeight | Number | 50 | No | The height (in pixels) of each item. |
style | Object | {} | No | Custom styles for the ScrollView . |
contentContainerStyle | Object | {} | No | Custom styles for the content container of the ScrollView . |
itemContainerStyle | Object | {} | No | Custom styles for the container of each individual item. |
itemBorderRadius | Number | 10 | No | The border radius of each draggable item. |
backgroundOnHold | String | #e3e3e3 | No | The background color of an item while it's being dragged. |
passVibration | Function | null | No | Function to trigger haptic feedback when an item starts moving. |
Notes
dataIDs
: Should be an array of unique identifiers (strings) that correspond to each list item.keyExtractor
: A function that extracts the key from each item in the data. Commonly, this will be the item's ID.renderGrip
: Customize the drag handle or "grip" for each item. Defaults to aText
grip if not provided.passVibration
: For iOS, you can useExpo Haptics
to trigger haptic feedback when the drag starts.
License
MIT
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago