Expo React Native拖拽FlatList项短暂跳回原位置问题求助
问题解决:DraggableFlatList拖拽跳回+Reanimated警告
问题现象
- 拖拽功能可用,但拖拽后的项目会短暂跳回原始位置
- 控制台出现Reanimated警告:
[Reanimated] Tried to modify key 'current' of an object which has been already passed to a worklet
解决方案
1. 修复Reanimated警告(根源问题)
这个警告大多是依赖版本不兼容导致的,Expo环境下必须保证react-native-draggable-flatlist、react-native-reanimated、react-native-gesture-handler三者版本与当前Expo SDK匹配:
- 先检查你的Expo SDK版本,对应安装兼容的依赖(比如SDK 50对应Reanimated ~3.6.0)
- 执行命令重装兼容版本:
npx expo install react-native-reanimated react-native-gesture-handler npm install react-native-draggable-flatlist@latest
- 确认
babel.config.js中添加了Reanimated插件(Expo通常自动配置,手动检查更稳妥):
module.exports = function(api) { api.cache(true); return { presets: ['babel-preset-expo'], plugins: ['react-native-reanimated/plugin'], }; };
2. 解决拖拽后跳回问题
跳回现象是因为外部状态更新与组件内部状态不同步,通过以下调整修复:
- 用
useCallback包裹onDragEnd函数,确保引用稳定,避免不必要的重渲染:
const handleDragEnd = useCallback(({ data }) => { setShopList(data); // 直接用组件返回的排序后数组,无需额外扩展 }, []);
- 修正
renderItem中的样式逻辑,避免因item.backgroundColor未定义导致的潜在渲染异常:
const renderItem = ({ item, drag, isActive }) => ( <TouchableOpacity onLongPress={drag} disabled={isActive} style={[ styles.item, { backgroundColor: isActive ? "red" : item.backgroundColor || "#fff", // 添加默认背景色 }, ]} > <View> <Text style={styles.text}>{item.title}</Text> </View> </TouchableOpacity> );
- 移除不必要的
useEffect日志(减少无意义的状态监听触发)
完整修正代码
import { View, Text, StyleSheet, TouchableOpacity, } from "react-native"; import DraggableFlatList from "react-native-draggable-flatlist"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { useState, useCallback } from "react"; import PrimaryButton from "../components/buttons/PrimaryButton"; const ListScreen = ({ route }) => { const [shopList, setShopList] = useState([ { id: "1", title: "Apfel", backgroundColor: "#fff" }, { id: "2", title: "Gurke", backgroundColor: "#fff" }, { id: "3", title: "Paprika", backgroundColor: "#fff" }, { id: "4", title: "Senf", backgroundColor: "#fff" }, { id: "5", title: "Brot", backgroundColor: "#fff" }, { id: "6", title: "Wurst", backgroundColor: "#fff" }, { id: "7", title: "Käse", backgroundColor: "#fff" }, ]); const handleDragEnd = useCallback(({ data }) => { setShopList(data); }, []); const renderItem = ({ item, drag, isActive }) => ( <TouchableOpacity onLongPress={drag} disabled={isActive} style={[ styles.item, { backgroundColor: isActive ? "red" : item.backgroundColor, }, ]} > <View> <Text style={styles.text}>{item.title}</Text> </View> </TouchableOpacity> ); return ( <GestureHandlerRootView style={{ flex: 1 }}> <View style={styles.container}> <DraggableFlatList data={shopList} keyExtractor={(item) => item.id} onDragEnd={handleDragEnd} renderItem={renderItem} /> <View style={styles.addButtonContainer}> <PrimaryButton>Add new item</PrimaryButton> </View> </View> </GestureHandlerRootView> ); }; export default ListScreen; const styles = StyleSheet.create({ container: { flex: 1, }, addButtonContainer: { padding: 10, }, text: { fontSize: 18, }, item: { padding: 20, marginVertical: 5, borderWidth: 1, borderColor: "#ddd", borderRadius: 5, }, });
额外排查点
- 确保
GestureHandlerRootView正确包裹了整个DraggableFlatList(你的代码已满足) - 不要在
onDragEnd中做异步操作,避免状态更新延迟 - 若问题仍存在,尝试清除Expo缓存:
npx expo start -c
内容的提问来源于stack exchange,提问作者Sabrina Müller
相关产品推荐
相关产品推荐

