React-Native 创建一个任务管理应用
在本文中,我们将为您介绍使用React Native构建基本任务管理应用的过程。该应用程序使用户能够轻松创建、编辑、完成/未完成和删除任务,为React Native的移动应用开发能力提供了简单而有影响力的入门介绍。
先决条件
- React Native入门
- Javascript
- React Native状态
- React Native Props
- Expo CLI
- Node.js和npm(Node Package Manager)
安装和配置React Native的步骤
步骤1:使用以下命令创建一个React Native应用:
npx create-expo-app taskmanager-app
步骤2:创建项目文件夹,即taskmanager-app,使用以下命令进行导航:
cd taskmanager-app
步骤2:使用外部库进行日期选择
在这个应用程序中,我们已经安装了 react native现代日期选择器 用于选择日期。
npm i react-native-modern-datepicker
项目结构
方式
此React Native代码片段可让您轻松构建一个简单的任务管理应用程序。它使用useState有效地管理状态,使您能够平滑处理任务数据、编辑功能和模态框可见性。该应用程序的界面呈现了一个可滚动的任务列表,每个任务都有一个标题。通过使用带有标题和内容输入的模态框,用户可以轻松地添加、编辑、完成/未完成和删除任务。
示例: 此示例使用react-native创建了一个任务管理应用程序。
// App.js
// Import necessary modules and components
import React, { useState } from "react";
import {
View,
Text,
TouchableOpacity,
Modal,
Button,
} from "react-native";
// Import TaskList component
import TaskList from "./components/TaskList";
// Import TaskModal component
import TaskModal from "./components/TaskModel";
import styles from "./styles"; // Import styles
// Define the main App component
const App = () => {
// Define state variables
// Array to store tasks
const [tasks, setTasks] = useState([]);
const [task, setTask] = useState({
title: "",
description: "",
status: "Pending",
deadline: "",
createdAt: "",
});
// Task object for creating/editing tasks
// Modal visibility
const [modalVisible, setModalVisible] = useState(false);
// Task being edited
const [editingTask, setEditingTask] = useState(null);
const [validationError, setValidationError] =
useState(false); // Validation flag
// Function to add a new task or update an existing task
const handleAddTask = () => {
if (
task.title.trim() !== "" &&
task.deadline !== ""
) {
const currentDate = new Date();
const formattedDate =
currentDate.toLocaleString();
if (editingTask) {
// If editing an existing task, update it
const updatedTasks = tasks.map((t) =>
t.id === editingTask.id
? { ...t, ...task }
: t
);
setTasks(updatedTasks);
setEditingTask(null);
} else {
// If adding a new task, create it
const newTask = {
id: Date.now(),
...task,
// Set the creation date and time as a string
createdAt: formattedDate,
};
setTasks([...tasks, newTask]);
}
// Clear the task input fields and reset state
setTask({
title: "",
description: "",
status: "Pending",
deadline: "",
createdAt: "",
});
// Close the modal
setModalVisible(false);
// Reset validation error
setValidationError(false);
} else {
// Show validation error if fields are not filled
setValidationError(true);
}
};
// Function to handle task editing
const handleEditTask = (task) => {
// Set the task being edited
setEditingTask(task);
// Pre-fill the input with task data
setTask(task);
// Open the modal for editing
setModalVisible(true);
};
// Function to delete a task
const handleDeleteTask = (taskId) => {
const updatedTasks = tasks.filter(
(t) => t.id !== taskId
);
setTasks(updatedTasks);
};
// Function to toggle task completion status
const handleToggleCompletion = (taskId) => {
const updatedTasks = tasks.map((t) =>
t.id === taskId
? {
...t,
status:
t.status === "Pending"
? "Completed"
: "Pending",
}
: t
);
setTasks(updatedTasks);
};
// Return the JSX for rendering the component
return (
<View style={styles.container}>
<Text style={styles.title}>Task Manager</Text>
{/* Render the TaskList component */}
<TaskList
tasks={tasks}
handleEditTask={handleEditTask}
handleToggleCompletion={
handleToggleCompletion
}
handleDeleteTask={handleDeleteTask}
/>
{/* Button to add or edit tasks */}
<TouchableOpacity
style={styles.addButton}
onPress={() => {
setEditingTask(null);
setTask({
title: "",
description: "",
status: "Pending",
deadline: "",
createdAt: "",
});
setModalVisible(true);
setValidationError(false);
}}>
<Text style={styles.addButtonText}>
{editingTask ? "Edit Task" : "Add Task"}
</Text>
</TouchableOpacity>
{/* Render the TaskModal component */}
<TaskModal
modalVisible={modalVisible}
task={task}
setTask={setTask}
handleAddTask={handleAddTask}
handleCancel={() => {
setEditingTask(null);
setTask({
title: "",
description: "",
status: "Pending",
deadline: "",
createdAt: "",
});
setModalVisible(false);
setValidationError(false);
}}
validationError={validationError}/>
</View>
);
};
// Export the App component as the default export
export default App;
// components/TaskList.js
import React from "react";
import { ScrollView } from "react-native";
import TaskItem from "./TaskItem";
import styles from "../styles";
const TaskList = ({
tasks,
handleEditTask,
handleToggleCompletion,
handleDeleteTask,
}) => {
return (
<ScrollView style={styles.taskList}>
{/* Scrollable container for the list of tasks */}
{tasks.map((t) => (
<TaskItem
// Use the task's ID as the key to
// uniquely identify each TaskItem
key={t.id}
// Pass the task object as a prop to TaskItem
task={t}
// Pass functions to handle editing,
// toggling completion, and deletion
handleEditTask={handleEditTask}
handleToggleCompletion={
handleToggleCompletion
}
handleDeleteTask={handleDeleteTask}
/>
))}
</ScrollView>
);
};
// Export the TaskList component
export default TaskList;
// components/TaskItem.js
import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
import styles from "../styles";
const TaskItem = ({
task,
handleEditTask,
handleToggleCompletion,
handleDeleteTask,
}) => {
return (
<View style={styles.taskItem}>
<View style={styles.taskTextContainer}>
<Text
style={[
styles.taskText,
task.status === "Completed" &&
styles.completedTaskText,
]}>
{task.title}
</Text>
<Text style={styles.taskDescription}>
{task.description}
</Text>
<Text style={styles.taskStatus}>
Status: {task.status}
</Text>
<Text style={styles.taskDeadline}>
Deadline: {task.deadline}
</Text>
<Text style={styles.taskCreatedAt}>
Created: {task.createdAt}
</Text>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={() => handleEditTask(task)}
style={[styles.editButton]}>
<Text style={styles.buttonText}>
Edit
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() =>
handleToggleCompletion(task.id)
}
style={[
styles.completeButton,
task.status === "Completed" &&
styles.completedButton,
]}>
<Text style={styles.buttonText}>
{task.status === "Completed"
? "Pending"
: "Completed"}
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() =>
handleDeleteTask(task.id)
}
style={[styles.deleteButton]}>
<Text style={styles.buttonText}>
Delete
</Text>
</TouchableOpacity>
</View>
</View>
);
};
export default TaskItem;
// components/TaskModal.js
import React from "react";
import {
View,
Text,
TextInput,
Button,
Modal,
} from "react-native";
import styles from "../styles";
import DatePicker from "react-native-modern-datepicker";
const TaskModal = ({
modalVisible,
task,
setTask,
handleAddTask,
handleCancel,
validationError,
}) => {
return (
<Modal
visible={modalVisible}
animationType="slide"
transparent={false}>
{/* Container for the modal */}
<View style={styles.modalContainer}>
<TextInput
style={styles.input}
placeholder="Title"
value={task.title}
onChangeText={(text) =>
setTask({ ...task, title: text })
}
// Update the title when text changes/>
<TextInput
style={styles.input}
placeholder="Description"
value={task.description}
onChangeText={(text) =>
setTask({
...task,
description: text,
})
}/>
<Text style={styles.inputLabel}>
Deadline:
</Text>
<DatePicker
style={styles.datePicker}
mode="date"
selected={task.deadline}
onDateChange={(date) =>
setTask({ ...task, deadline: date })
}/>
{validationError && (
<Text style={styles.errorText}>
Please fill in all fields correctly.
</Text>
)}
<Button
// Display "Update" when editing an existing
// task, "Add" when adding a new task
title={task.id ? "Update" : "Add"}
// Call the handleAddTask function
// when the button is pressed
onPress={handleAddTask}
// Set the button color
color="#007BFF"/>
<Button
title="Cancel"
onPress={handleCancel}
color="#FF3B30"/>
</View>
</Modal>
);
};
export default TaskModal;
// styles.js
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: "#f7f7f7",
},
title: {
fontSize: 28,
fontWeight: "bold",
marginBottom: 20,
color: "#333",
textAlign: "center",
},
taskList: {
flex: 1,
},
taskItem: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "#fff",
marginBottom: 10,
padding: 15,
borderRadius: 10,
},
taskTextContainer: {
flex: 1,
},
taskText: {
fontSize: 18,
fontWeight: "bold",
color: "#333",
},
completedTaskText: {
textDecorationLine: "line-through",
color: "gray",
},
taskDescription: {
fontSize: 16,
color: "#666",
},
taskTime: {
fontSize: 14,
color: "#666",
},
taskStatus: {
fontSize: 16,
color: "#666",
},
buttonContainer: {
// Or 'row' depending on your layout
flexDirection: "column",
// Adjust the value as needed for the
// desired spacing
marginVertical: 2,
},
editButton: {
backgroundColor: "#007BFF",
borderRadius: 5,
padding: 10,
marginRight: 10,
width: 110,
},
button: {
marginBottom: 10,
},
completeButton: {
backgroundColor: "#4CAF50",
borderRadius: 5,
padding: 10,
marginRight: 10,
width: 110,
},
completedButton: {
backgroundColor: "#808080",
},
buttonText: {
color: "#fff",
fontSize: 15,
},
deleteButton: {
backgroundColor: "#FF9500",
borderRadius: 5,
padding: 10,
width: 110,
},
addButton: {
alignItems: "center",
justifyContent: "center",
backgroundColor: "#007BFF",
paddingVertical: 15,
borderRadius: 10,
marginTop: 20,
},
addButtonText: {
color: "#fff",
fontSize: 18,
fontWeight: "bold",
},
modalContainer: {
flex: 1,
padding: 20,
backgroundColor: "#fff",
},
input: {
borderWidth: 1,
borderColor: "#ccc",
padding: 10,
marginBottom: 20,
borderRadius: 5,
fontSize: 16,
},
inputLabel: {
fontSize: 16,
fontWeight: "bold",
},
errorText: {
color: "#FF3B30",
fontSize: 16,
marginBottom: 10,
},
taskDeadline: {
color: "#FF3B12",
},
taskCreatedAt: {
color: "#5497FF",
},
});
export default styles;
运行步骤
打开终端并输入以下命令运行React Native应用程序。
npx expo start
在Android上运行:
npx react-native run-android
在iOS上运行:
npx react-native run-ios
输出: