使用 Next.js + Remult 创建一个待办事项(四)
Yakim Zhang

实现增改删查

支持任务重命名,修改状态(修改)

  1. tasks.map 修改组件内迭代的内容 Home 以包括以下 handleChange 函数和 input 元素。

pages/index.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const Home: NextPage = () => {
const [tasks, setTasks] = useState<Task[]>([]);
const [hideCompleted, setHideCompleted] = useState(false);

useEffect(() => {
fetchTasks(hideCompleted).then(setTasks);
}, [hideCompleted]);

return (
<div>
<input
type="checkbox"
checked={hideCompleted}
onChange={(e) => setHideCompleted(e.target.checked)}
/>{" "}
Hide Completed
<main>
{tasks.map((task) => {
const handleChange = (values: Partial<Task>) => {
setTasks(
tasks.map((t) => (t === task ? { ...task, ...values } : t))
);
};

return (
<div key={task.id}>
<input
type="checkbox"
checked={task.completed}
onChange={(e) => handleChange({ completed: e.target.checked })}
/>
<input
value={task.title}
onChange={(e) => handleChange({ title: e.target.value })}
/>
</div>
);
})}
</main>
</div>
);
};

该 handleChange 函数只是 tasks 用包含所有未更改任务的新数组和包含修改后的当前任务的新版本替换状态 values。

浏览器刷新后,任务可以重命名并标记为已完成。

  1. 添加一个 saveTask 将任务状态保存到后端数据库的函数,以及一个调用它的保存按钮。

pages/index.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
tasks.map((task) => {
const handleChange = (values: Partial<Task>) => {
setTasks(tasks.map((t) => (t === task ? { ...task, ...values } : t)));
};

const saveTask = async () => {
const savedTask = await remult.repo(Task).save(task);
setTasks(tasks.map((t) => (t === task ? savedTask : t)));
};

return (
<div key={task.id}>
<input
type="checkbox"
checked={task.completed}
onChange={(e) => handleChange({ completed: e.target.checked })}
/>
<input
value={task.title}
onChange={(e) => handleChange({ title: e.target.value })}
/>
<button onClick={saveTask}>Save</button>
</div>
);
});
}

为什么保存任务后更新任务数组

Remult 的 Repository.save 方法发出一个 PUT 或一个 POST 请求,这取决于对象中是否存在一个 id 值 Task。

在本教程的下一节中,我们将通过创建 Task 对象并使用相同的 saveTask 函数保存它们来将新任务添加到列表中。因此,为了确保新创建的任务只被 POST-ed 一次,我们必须将其替换为 的返回值 Repository.save,其中包含一个 id.

添加新任务(新增)

在组件中添加 addTask 功能和 Add Task :buttonHome

pages/index.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const Home: NextPage = () => {
const [tasks, setTasks] = useState<Task[]>([]);
const [hideCompleted, setHideCompleted] = useState(false);

useEffect(() => {
fetchTasks(hideCompleted).then(setTasks);
}, [hideCompleted]);

const addTask = () => {
setTasks([...tasks, new Task()]);
};

return (
<div>
<main>
<input
type="checkbox"
checked={hideCompleted}
onChange={(e) => setHideCompleted(e.target.checked)}
/>{" "}
Hide Completed
<hr />
{tasks.map((task) => {
const handleChange = (values: Partial<Task>) => {
setTasks(
tasks.map((t) => (t === task ? { ...task, ...values } : t))
);
};

const saveTask = async () => {
const savedTask = await remult.repo(Task).save(task);
setTasks(tasks.map((t) => (t === task ? savedTask : t)));
};

return (
<div key={task.id}>
<input
type="checkbox"
checked={task.completed}
onChange={(e) => handleChange({ completed: e.target.checked })}
/>
<input
value={task.title}
onChange={(e) => handleChange({ title: e.target.value })}
/>
<button onClick={saveTask}>Save</button>
</div>
);
})}
</main>
<button onClick={addTask}>Add Task</button>
</div>
);
};

删除任务

让我们在列表中每个任务的保存按钮旁边添加一个删除按钮。

在组件部分的迭代中添加突出显示的 deleteTask 功能和删除
button tasks.map return Home

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
tasks.map((task) => {
const handleChange = (values: Partial<Task>) => {
setTasks(tasks.map((t) => (t === task ? { ...task, ...values } : t)));
};

const saveTask = async () => {
const savedTask = await remult.repo(Task).save(task);
setTasks(tasks.map((t) => (t === task ? savedTask : t)));
};

const deleteTask = async () => {
await remult.repo(Task).delete(task);
setTasks(tasks.filter((t) => t !== task));
};

return (
<div key={task.id}>
<input
type="checkbox"
checked={task.completed}
onChange={(e) => handleChange({ completed: e.target.checked })}
/>
<input
value={task.title}
onChange={(e) => handleChange({ title: e.target.value })}
/>
<button onClick={saveTask}>Save</button>
<button onClick={deleteTask}>Delete</button>
</div>
);
});
}