You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo React Native拖拽FlatList项短暂跳回原位置问题求助

问题解决:DraggableFlatList拖拽跳回+Reanimated警告

问题现象

  1. 拖拽功能可用,但拖拽后的项目会短暂跳回原始位置
  2. 控制台出现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:53:14