我們先安裝MMKV來管理我們的資料。react-native-mmkv
,這裡安裝2.12.2
版本。記得要重新build。
創建一個用來操作Task的service。
// src\services\task.service.tsx
import { MMKV } from 'react-native-mmkv';
import { Task } from '../types';
const storage = new MMKV();
const TASKS_KEY = 'tasks';
export const TaskStorage = {
saveTasks: (tasks: Task[]) => {
storage.set(TASKS_KEY, JSON.stringify(tasks));
},
getTasks: (): Task[] => {
const tasksJson = storage.getString(TASKS_KEY);
return tasksJson ? JSON.parse(tasksJson) : [];
},
addTask: (task: Task) => {
const tasks = TaskStorage.getTasks();
tasks.push(task);
TaskStorage.saveTasks(tasks);
},
updateTask: (updatedTask: Task) => {
const tasks = TaskStorage.getTasks();
const index = tasks.findIndex(task => task.id === updatedTask.id);
if (index !== -1) {
tasks[index] = updatedTask;
TaskStorage.saveTasks(tasks);
}
},
deleteTask: (taskId: string) => {
const tasks = TaskStorage.getTasks();
const updatedTasks = tasks.filter(task => task.id !== taskId);
TaskStorage.saveTasks(updatedTasks);
},
};
並修改我們的atorm中的task:
import { atom } from 'jotai';
import { Task, User } from '../types';
import { TaskService } from '../services/task.service';
export const userAtom = atom<User | null>(null);
export const tasksAtom = atom<Task[]>(TaskService.getTasks());
接著,我們來一一更新 home.page.tsx
、add-task.page.tsx
和 task-detail.page.tsx
這些頁面。
更新home page
// src\pages\home.page.tsx
// ...
type HomePageProps = {
isDarkMode: boolean;
onTaskSelect?: (task: Task) => void;
};
const HomePage: React.FC<HomePageProps> = ({ isDarkMode, onTaskSelect }) => {
const [tasks, setTasks] = useAtom(tasksAtom);
useEffect(() => {
const loadedTasks = TaskService.getTasks();
setTasks(loadedTasks);
}, [setTasks]);
const toggleTaskStatus = useCallback((id: string) => {
const updatedTasks = tasks.map(task =>
task.id === id ? { ...task, isDone: !task.isDone } : task
);
setTasks(updatedTasks);
TaskService.saveTasks(updatedTasks);
}, [tasks, setTasks]);
const deleteTask = useCallback((id: string) => {
const updatedTasks = tasks.filter(task => task.id !== id);
setTasks(updatedTasks);
TaskService.deleteTask(id);
}, [tasks, setTasks]);
const renderRightActions = useCallback((id: string) => {
return (
<TouchableOpacity
style={styles.deleteButton}
onPress={() => deleteTask(id)}
>
<Text style={styles.deleteButtonText}>Delete</Text>
</TouchableOpacity>
);
}, [deleteTask]);
// ...
更新add頁面中的handleSubmit
// src\pages\add-task.page.tsx
import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView, Alert } from 'react-native';
import { useSetAtom } from 'jotai';
import { tasksAtom } from '../stores/atoms';
import { Task, Tags } from '../types/index';
import DatePicker from 'react-native-date-picker';
import { TaskService } from '../services/task.service';
type AddTaskPageProps = {
isDarkMode: boolean;
};
const AddTaskPage: React.FC<AddTaskPageProps> = ({ isDarkMode }) => {
// ...
const handleSubmit = () => {
const newTask: Task = {
id: Date.now().toString(),
title,
startDate: startDate ? startDate.toISOString().split('T')[0] : null,
endDate: endDate ? endDate.toISOString().split('T')[0] : null,
description,
isDone: false,
tags,
subTasks: [],
};
const validationErrors = validateTask(newTask);
if (validationErrors.length > 0) {
Alert.alert('Validation Error', validationErrors.join('\n'));
return;
}
TaskService.addTask(newTask);
setTasks(prevTasks => [...prevTasks, newTask]);
// Reset form fields
setTitle('');
setDescription('');
setStartDate(null);
setEndDate(null);
setTags([]);
Alert.alert('Success', 'Task added successfully');
};
接著修改一下detail部分。
// src\pages\task-detail.page.tsx
import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Switch, TextInput, ScrollView } from 'react-native';
import { Task } from '../types';
import { useAtom } from 'jotai';
import { tasksAtom } from '../stores/atoms';
import { TaskService } from '../services/task.service';
type TaskDetailsPageProps = {
isDarkMode: boolean;
task: Task;
onBack: () => void;
};
const TaskDetailsPage: React.FC<TaskDetailsPageProps> = ({
isDarkMode,
task,
onBack,
}) => {
const [isEditing, setIsEditing] = useState(false);
const [editedTask, setEditedTask] = useState(task);
const [, setTasks] = useAtom(tasksAtom);
const handleEdit = useCallback(() => {
setIsEditing(true);
}, []);
const handleSave = useCallback(() => {
TaskService.updateTask(editedTask);
setTasks(prevTasks => prevTasks.map(t => t.id === editedTask.id ? editedTask : t));
setIsEditing(false);
}, [editedTask, setTasks]);
const handleDelete = useCallback(() => {
TaskService.deleteTask(task.id);
setTasks(prevTasks => prevTasks.filter(t => t.id !== task.id));
onBack();
}, [task.id, setTasks, onBack]);
const toggleCompletion = useCallback(() => {
const updatedTask = { ...editedTask, isDone: !editedTask.isDone };
setEditedTask(updatedTask);
TaskService.updateTask(updatedTask);
setTasks(prevTasks => prevTasks.map(t => t.id === updatedTask.id ? updatedTask : t));
}, [editedTask, setTasks]);
// ...
目前我們已經將部分的Task資料存儲方法和操作改成使用了MMKV,明天會繼續把User部分也使用相關的本地存儲方法。