我在 React Native 上有一个非常简单的基于列表的任务管理器: https ://snack.expo.dev/@bradbarnes99/test-dummy-tasky
代码工作得很好,直到我尝试将 react-native-draggable-flatlist 模块适应于此,现在我得到:“文本字符串必须在组件内呈现”
这是来自收到错误的容器的代码。
import React from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
TextInput,
View,
TouchableOpacity,
StatusBar,
Alert,
ScrollView,
} from 'react-native';
import DraggableFlatList from 'react-native-draggable-flatlist';
import { FontAwesome5 } from '@expo/vector-icons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import uuid from 'react-native-uuid';
import BlueButton from '../components/BlueButton';
import Header from '../components/Header';
import Checkbox from '../components/Checkbox';
let anyChecked = false;
export default class MainScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
addTaskValue: '',
taskers: [],
};
this.getIt();
}
addTaskTextHandler = (val) => {
this.setState({ addTaskValue: val });
};
addTaskButtonHandler = () => {
let key = uuid.v4();
let task = this.state.addTaskValue;
task = task.trim();
let order = this.state.taskers.length + 1;
const taskToAdd = { key, order, title: task, checked: false };
if (task) {
this.setState({ taskers: [...this.state.taskers, taskToAdd] });
this.storeIt();
} else {
alert('Enter a task');
}
this.setState({ addTaskValue: '' });
};
storeIt = async () => {
const jsonValue = JSON.stringify(this.state.taskers);
try {
await AsyncStorage.setItem('taskKey', jsonValue);
} catch (err) {
console.log(err);
}
};
onChecked = (key) => {
const index = this.state.taskers.findIndex(function (o) {
return o.key === key;
});
let tempTaskers = [...this.state.taskers];
tempTaskers[index].checked =
tempTaskers[index].checked === true ? false : true;
console.log(tempTaskers[index].checked);
this.setState({ taskers: [...tempTaskers] });
this.storeIt();
this.anyCheckedTasks();
};
anyCheckedTasks = () => {
let checked = false;
for (let i = 0; i < this.state.taskers.length; i++) {
if (this.state.taskers[i].checked === true) {
anyChecked = true;
this.forceUpdate();
return;
}
}
anyChecked = false;
this.forceUpdate();
return;
};
getIt = async () => {
try {
const value = await AsyncStorage.getItem('taskKey');
if (value != null) {
this.setState({ taskers: JSON.parse(value) });
} else {
this.setState({ taskers: [] });
}
this.anyCheckedTasks();
} catch (err) {
console.err(err);
}
};
deleteTasksButtonHandler = () => {
Alert.alert('Warning', 'Delete All Tasks?', [
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{ text: 'OK', onPress: () => this.deleteTasks() },
]);
};
deleteTasks = async () => {
this.setState({ taskers: [] });
await this.storeIt();
this.anyCheckedTasks();
this.forceUpdate();
};
deleteCompletedTasksButtonHandler = () => {
Alert.alert('Warning', 'Delete Completed Tasks?', [
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{ text: 'OK', onPress: () => this.deleteCompletedTasks() },
]);
};
deleteCompletedTasks = async () => {
const uncheckedTasks = this.state.taskers.filter((task) => {
return task.checked === false;
});
this.setState({ taskers: uncheckedTasks });
await this.storeIt();
this.anyCheckedTasks();
this.forceUpdate();
};
DeleteOneTaskButtonHandler = async (key) => {
const index = this.state.taskers.findIndex(function (o) {
return o.key === key;
});
let tempTasks = this.state.taskers;
if (index !== -1) tempTasks.splice(index, 1);
this.setState({ taskers: tempTasks });
await this.storeIt();
this.anyCheckedTasks();
this.forceUpdate();
};
renderItem = ({ item, index, drag, isActive }) => {
return (
<View style={styles.checkbox}>
<TouchableOpacity onLongPress={drag}>
<Checkbox
key={item.key}
title={item.title}
isChecked={item.checked}
onToggleChange={() => this.onChecked(item.key)}
/>
</TouchableOpacity>
<FontAwesome5
name="times-circle"
size={24}
color="#BCE0FD"
style={styles.deleteTask}
onPress={() => {
this.DeleteOneTaskButtonHandler(item.key);
}}
/>
</View>
);
};
render() {
let { title, style } = this.props;
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="dark-content" />
<Header instructions="You are the Task Master!" />
<View style={styles.body}>
<Text style={styles.addTask}>Add Task</Text>
<View style={styles.addTaskRow}>
<TextInput
style={styles.input}
value={this.state.addTaskValue}
onChangeText={this.addTaskTextHandler}
/>
<TouchableOpacity
style={[styles.addButton, style]}
onPress={this.addTaskButtonHandler}>
<Text style={styles.addButtonText}>Add</Text>
</TouchableOpacity>
</View>
<ScrollView>
{this.state.taskers.length > 0 && (
<>
<DraggableFlatList
data={this.state.taskers}
renderItem={this.renderItem}
keyExtractor={(item, index) => item.key}
onDragEnd={({ data }) => this.setState({ data })}
/>
</>
)}
{this.state.taskers.length > 0 && (
<View style={{ margin: 25 }}>
<BlueButton
title="Delete All Tasks"
style={
anyChecked
? { width: '100%', marginBottom: 0 }
: { width: '100%', marginBottom: 225 }
}
onPress={this.deleteTasksButtonHandler}
/>
</View>
)}
{anyChecked && (
<View style={{ margin: 25 }}>
<BlueButton
title="Delete Completed Tasks"
style={{ width: '100%', marginTop: -25, marginBottom: 225 }}
onPress={this.deleteCompletedTasksButtonHandler}
/>
</View>
)}
</ScrollView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
body: {
margin: 25,
},
addTask: {
color: '#2699FB',
marginBottom: 10,
},
addTaskRow: {
flexDirection: 'row',
marginBottom: 25,
},
input: {
borderColor: '#2699FB',
borderWidth: 2,
borderStyle: 'solid',
paddingTop: 15,
paddingBottom: 15,
marginBottom: 30,
paddingLeft: 10,
paddingRight: 10,
width: '80%',
marginRight: 10,
},
addButton: {
backgroundColor: '#BCE0FD',
padding: 15,
borderRadius: 4,
height: '63%',
},
addButtonText: {
color: '#2697FB',
fontWeight: 'bold',
textAlign: 'center',
fontSize: 16,
textTransform: 'uppercase',
},
checkbox: {
flex: 1,
flexDirection: 'row',
marginBottom: 15,
},
deleteTask: {
marginLeft: 'auto',
alignSelf: 'center',
transform: 'translateY: -80px',
},
});
这是 Checkbox 组件中的代码,以防出现触发错误的情况...
import React from 'react';
import {View, Text, Image, StyleSheet, TouchableOpacity} from 'react-native';
const imgCheck = require('../assets/check.png');
export default class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = {
isComplete: props.isChecked,
};
}
toggleCheck() {
let status = this.state.isComplete;
this.setState({
isComplete: !status,
});
// Notify any listeners of the state change
if (this.props.onToggleChange) {
this.props.onToggleChange(this.props.key, this.props.item, !status);
}
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => this.toggleCheck()}>
<View style={this.state.isComplete ? styles.boxChecked : styles.box}>
{this.state.isComplete && (
<Image source={imgCheck} style={styles.check} />
)}
</View>
</TouchableOpacity>
<Text
style={this.state.isComplete ? styles.titleComplete : styles.title}>
{this.props.title}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
padding: 5,
backgroundColor: "white",
},
box: {
borderColor: '#2699FB',
borderWidth: 2,
borderStyle: 'solid',
padding: 3,
width: 30,
height: 30,
justifyContent: 'center',
alignItems: 'center',
},
boxChecked: {
borderColor: '#2699FB',
borderWidth: 2,
borderStyle: 'solid',
padding: 3,
width: 30,
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#2699FB',
},
check: {
width: 24,
height: 24,
},
title: {
color: '#2699FB',
fontWeight: 'bold',
marginLeft: 15,
fontSize: 18,
maxWidth: '82%'
},
titleComplete: {
color: 'gray',
marginLeft: 15,
fontSize: 18,
maxWidth: '82%'
},
});
我不知所措。我在 MainScreen.js 中删除了我的所有评论,以防万一引起问题。
你们中的任何人都知道为什么我会收到此错误吗?
我将上面的链接包含到我的 expo.dev 小吃的所有代码中。
提前致谢!