javascript - 我如何将 react-native-draggable-flatlist 实现为函数组件而不是类?

标签 javascript reactjs react-native

更新
将“setData({ data })”更改为“setData(data)”并重新启动 iOS 模拟器后解决
原帖
https://www.npmjs.com/package/react-native-draggable-flatlist示例使用类组件,但我更喜欢使用函数组件。下面是我作为功能组件实现的尝试,但我遇到了一个错误(也在下面)。重新排序单个列表项后发生错误,然后列表消失。
功能组件尝试

import React, { useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import DraggableFlatList from 'react-native-draggable-flatlist';
import ScreenTitle from '../components/ScreenTitle';
import AppScreen from './AppScreen';

function MyMorningScreen(props) {
  const [data, setData] = useState([
    {
      order: 1,
      label: 'Start Timeular',
    },
    {
      order: 2,
      label: 'Workout',
    },
    {
      order: 3,
      label: 'Shower',
    },
  ]);

  const renderItem = ({ item, index, drag, isActive }) => (
    <TouchableOpacity style={styles.item} onLongPress={drag}>
      <Text>{item.label}</Text>
    </TouchableOpacity>
  );
  return (
    <AppScreen style={styles.screen}>
      <ScreenTitle title="My Morning" />
      <View style={{ flex: 1 }}>
        <DraggableFlatList
          data={data}
          renderItem={renderItem}
          keyExtractor={(item, index) => index.toString()}
          onDragEnd={({ data }) => setData({ data })}
        />
      </View>
    </AppScreen>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
  },
});

export default MyMorningScreen;

错误
[Unhandled promise rejection: TypeError: undefined is not a function (near '...this.props.data.forEach...')]
- node_modules/react-native-draggable-flatlist/lib/index.js:192:20 in __generator$argument_1
* http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:135784:24 in step
* http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:135686:72 in <unknown>
- node_modules/react-native/node_modules/promise/setimmediate/core.js:45:6 in tryCallTwo
- node_modules/react-native/node_modules/promise/setimmediate/core.js:200:22 in doResolve
- node_modules/react-native/node_modules/promise/setimmediate/core.js:66:11 in Promise
* http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:135665:35 in <unknown>
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:15732:12 in commitLifeCycles
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:18744:22 in commitLayoutEffects
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:265:4 in invokeGuardedCallbackImpl
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:476:2 in invokeGuardedCallback
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:18483:29 in commitRootImpl
* [native code]:null in commitRootImpl
- node_modules/scheduler/cjs/scheduler.development.js:653:23 in unstable_runWithPriority
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:18317:17 in commitRoot
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:17697:12 in performSyncWorkOnRoot
* [native code]:null in performSyncWorkOnRoot
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5321:31 in runWithPriority$argument_1
- node_modules/scheduler/cjs/scheduler.development.js:653:23 in unstable_runWithPriority
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5316:21 in flushSyncCallbackQueueImpl
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5304:28 in flushSyncCallbackQueue
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:17125:30 in scheduleUpdateOnFiber
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:11003:16 in dispatchAction
* [native code]:null in dispatchAction
* app/screens/MyMorningScreen.js:36:21 in DraggableFlatList.props.onDragEnd
* http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:136087:19 in <unknown>
- node_modules/react-native-reanimated/src/core/AnimatedCall.js:9:15 in listener
- node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10 in emit
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:416:4 in __callFunction
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:109:6 in __guard$argument_0
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:364:10 in __guard
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
* [native code]:null in callFunctionReturnFlushedQueue

最佳答案

工作应用程序:Expo Snack
enter image description here

// Try updating state like shown below: 
/*.....*/
onDragEnd={({ data }) => setData(data)}
更新了带有复选框实现的完整代码:
import React, { useState } from 'react';
import {
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  CheckBox,
} from 'react-native';
import DraggableFlatList from 'react-native-draggable-flatlist';

const initialData = [
  {
    order: 1,
    label: 'Start Timeular',
    isCheked: false,
  },
  {
    order: 2,
    label: 'Workout',
    isCheked: false,
  },
  {
    order: 3,
    label: 'Shower',
    isCheked: true,
  },
];
function MyMorningScreen(props) {
  const [data, setData] = useState(initialData);

  const renderItem = ({ item, index, drag, isActive }) => (
    <View style={styles.item}>
      <TouchableOpacity onLongPress={drag}>
        <Text>{item?.label}</Text>
      </TouchableOpacity>
      <CheckBox
        value={item.isCheked}
        onChange={() => {
          handleCheck(item.label);
        }}
      />
    </View>
  );

  const handleCheck = (label) => {
    let updated = [...data];
    updated = updated.map((task, index) => {
      if (label === task.label) {
        return { ...task, isCheked: !task.isCheked };
      }
      return task;
    });
    setData(updated);
  };
  return (
    <View style={styles.screen}>
      <View style={{ flex: 1 }}>
        <DraggableFlatList
          data={data}
          renderItem={renderItem}
          keyExtractor={(item, index) => index.toString()}
          onDragEnd={({ data }) => setData(data)}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  screen: {
    marginTop: 24,
    flex: 1,
    backgroundColor: '#212121',
  },
  item: {
    backgroundColor: 'white',
    marginTop: 10,
    padding: 20,
    marginHorizontal: 10,
    borderRadius: 10,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
});

export default MyMorningScreen;

关于javascript - 我如何将 react-native-draggable-flatlist 实现为函数组件而不是类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65591640/

相关文章:

javascript - 在 fetch 启动后制作不可点击的按钮 React Native

javascript - 计算有多少字符(来自字符串)可以放入一个 div 而无需换行?

javascript - JSON.parse() 不适用于变量类型字符串,但如果直接使用,它可以处理其内容

javascript - 在 React 中 props 更改时重新渲染子组件的最佳解决方案是什么?

authentication - 如何使用 REST API 通过 OAuth2 和 React Native 进行身份验证?

firebase - 安装 Firebase 后运行 pod install --repo-update 时出错

javascript - 如何跳出 querySnapshot forEach 循环方法?

javascript - 未处理的PromiseRejection警告: Unhandled promise rejection (rejection id: 1): ReferenceError: registrationTokens is not defined

javascript - 尽管我可以在控制台上看到 Blob 图像,但它不会显示在 UI 上

javascript - 如何使用twilio客户端在reactjs中发送电话验证码?