-
-
Notifications
You must be signed in to change notification settings - Fork 447
Open
Description
Describe the bug
After an upgrade to Expo SDK version 52, and all relevant dependencies, a previously working horizontal draggable flatlist exhibits two incorrect behaviors:
- Drag and drop rearranging the values of the list works, but upon drop, the entries flash back to their original order for a second before settling in the final, correct positions. This make the rearranging feel and look extremely jittery.
- With the drag and drop, the item we are dragging sometimes does not resize back down to its normal size after being dropped, leading to an oversized item in the lift. Screenshot of this is attached.
Full code of the component is attached below.
Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).
- react-native-draggable-flatlist version: ^4.0.1
- Platform: ios
- React Native or Expo version: expo 52.0.4
- Reanimated version: 3.16.1
- React Native Gesture Handler version: ~2.20.2
- React Native version: 0.76.1
Previous Platform & Dependencies where this code worked
- react-native-draggable-flatlist version: ^4.0.1
- Platform: ios
- React Native or Expo version: expo 51.0.6
- Reanimated version: ~3.10.1
- React Native Gesture Handler version: ^2.16.1
- React Native version: 0.74.1
const Favorites = ({ favoriteBooks, isLoading, navigation, onReorder, isCurrentUser, userDetails }) => {
const { theme } = useContext(ThemeContext);
const styles = getDynamicStyles(theme);
const [isEditMode, setIsEditMode] = useState(false);
const [data, setData] = useState(favoriteBooks);
useEffect(() => {
setData(favoriteBooks);
}, [favoriteBooks]);
const LibraryButton = () => (
<TouchableOpacity
onPress={() => navigation.navigate('Library', {
userDetails: userDetails
})}
style={[
styles.libraryButton,
{ opacity: isLoading ? 0.5 : 1 }
]}
disabled={isLoading}
>
<Ionicons
name="library-outline"
size={15}
color={theme.distinctAccentColor}
style={{ marginRight: 5 }}
/>
<Text style={[styles.libraryButtonText, { color: theme.distinctAccentColor }]}>
{isLoading ? 'Loading...' : 'View Library'}
</Text>
</TouchableOpacity>
);
const toggleEditMode = async () => {
if (isCurrentUser) {
if (isEditMode) {
// Exiting edit mode, save the new order
const newOrder = data.map(item => item.id);
try {
const result = await BookService.reorderFavorites(newOrder);
if (result) {
onReorder(newOrder);
setIsEditMode(false);
} else {
Alert.alert("Error", "Failed to save the new order. Please try again.");
}
} catch (error) {
console.error('Error saving favorites order:', error);
Alert.alert("Error", "An error occurred while saving. Please try again.");
}
} else {
// Entering edit mode
setIsEditMode(true);
}
}
};
useEffect(() => {
console.log("Setting navigation options. isEditMode:", isEditMode);
navigation.setOptions({
swipeEnabled: !isEditMode,
});
}, [isEditMode, navigation]);
const renderPlaceholderCard = () => {
return (
<View style={styles.placeholderCard}>
<Ionicons name="sparkles-outline" size={24} color={theme.subtleAccentColor} />
<Text style={styles.placeholderText}>Future Gem</Text>
</View>
);
};
const handleDragStart = useCallback(() => {
console.log("Drag started");
}, []);
const handleDragEnd = useCallback(({ data: newData, from, to }) => {
console.log("Drag ended. From:", from, "To:", to);
console.log("New data order:", newData.map(item => item.id));
setData(newData);
onReorder(newData.map(item => item.id));
}, [onReorder]);
const renderBookItem = useCallback(({ item, drag, isActive }) => {
if (item === 'placeholder') {
return renderPlaceholderCard();
}
if (isLoading) {
return (
<View style={styles.bookItem}>
<ShimmerPlaceholder
width={styles.thumbnail.width}
height={styles.thumbnail.height}
style={styles.thumbnail}
/>
<View style={[styles.bookTitle, { height: 16 }]} />
<View style={[styles.bookAuthor, { height: 12 }]} />
</View>
);
}
const book = item.book;
const navigateToBookDetails = () => {
if (!isEditMode) {
navigation.navigate('BookDetails', { book });
}
};
return (
<TouchableOpacity
onPress={navigateToBookDetails}
onLongPress={() => {
console.log("Long press detected on book:", book.title, "isEditMode:", isEditMode);
if (isEditMode) {
console.log("Initiating drag for book:", book.title);
drag();
}
}}
style={[
styles.bookItem,
isActive && styles.activeBookItem,
]}
>
<Image source={{ uri: book.cover_url }} style={styles.thumbnail} />
<Text allowFontScaling={false} style={styles.bookTitle}>{truncate(book.title, 15)}</Text>
<Text allowFontScaling={false} style={styles.bookAuthor}>{truncate(book.author, 15)}</Text>
</TouchableOpacity>
);
}, [isEditMode, isLoading, navigation, styles, theme]);
const favoritesList = isLoading
? [1, 2, 3, 4, 5]
: [...data];
while (favoritesList.length < 5) {
favoritesList.push('placeholder');
}
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={styles.favoritesContainer}>
<View style={styles.favoritesHeaderContainer}>
<Text allowFontScaling={false} style={styles.favoritesHeader}>Favorites</Text>
{!isCurrentUser && <LibraryButton />}
{isCurrentUser && (
<TouchableOpacity onPress={toggleEditMode} style={styles.editButton}>
<Ionicons
name={isEditMode ? "save-outline" : "pencil-outline"}
size={20}
color={theme.mainTextColor}
/>
</TouchableOpacity>
)}
</View>
<DraggableFlatList
data={favoritesList}
renderItem={renderBookItem}
keyExtractor={(item, index) => {
if (isLoading) return `loading-${index}`;
if (item === 'placeholder') return `placeholder-${index}`;
return item.id ? item.id.toString() : `item-${index}`;
}}
horizontal
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
showsHorizontalScrollIndicator={false}
style={styles.favoritesFlatList}
contentContainerStyle={styles.favoritesContent}
ItemSeparatorComponent={() => <View style={styles.favoritesItemSeparator} />}
activationDistance={0}
dragItemOverflow={true}
dragHitSlop={{ top: 10, bottom: 10, left: 20, right: 20 }}
autoscrollThreshold={20}
autoscrollSpeed={100}
/>
<View style={styles.swipeGuideContainer}>
<Icon name="arrow-back" size={15} color={theme.subtleAccentColor} />
<Icon name="arrow-forward" size={15} color={theme.subtleAccentColor} />
</View>
</View>
</GestureHandlerRootView>
);
};`
Unuuuuu, i-soy, nishanthvijayan, MeNoKVN, Sabrinovsky and 6 morefonodi and kevinmcalear
Metadata
Metadata
Assignees
Labels
No labels
