Reputation: 135
Resolved after changing "setData({ data })" to "setData(data)" and restarting iOS Simulator
https://www.npmjs.com/package/react-native-draggable-flatlist example uses a class component but I'd prefer to use a function component. My attempt at implementing as a function component is below, but I am running into an error (also below). The error occurs after reordering a single list item, then the list disappears.
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
Upvotes: 5
Views: 8791
Reputation: 10675
Working App: Expo Snack
// Try updating state like shown below:
/*.....*/
onDragEnd={({ data }) => setData(data)}
UPDATED Full Code with Checkbox implementation:
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;
Upvotes: 7