Proyek: Todo App Full
Tugas: bangun aplikasi todo lengkap dengan Server Actions.
Misi: Todo App dari nol
Empat modul terakhir memberimu semua senjata: Server Actions, validasi, pending state, useActionState, optimistic update, dan revalidatePath. Sekarang rangkai semuanya menjadi aplikasi todo yang benar-benar berfungsi. Ini peta langkahnya, bukan kode jadi. Kamu yang menulis kodenya.
Langkah 0: struktur file
Buat folder app/todos/ dengan file-file ini, masing-masing satu tanggung jawab:
app/todos/page.tsx, Server Component: fetch data, render daftar + formapp/todos/actions.ts, semua Server Actions (tambah, toggle, hapus)app/todos/data.ts, lapisan penyimpanan (baca/tulis JSON)app/todos/AddForm.tsx, Client Component: form tambah + pesan errorapp/todos/TodoList.tsx, Client Component: daftar + toggle optimistik
Satu file satu tugas, jadi kalau ada bug kamu langsung tahu file mana yang dibuka.
Langkah 1: lapisan data dulu
Mulai dari data.ts: simpan todos di file JSON (todos.json di root project) lewat getTodos() dan saveTodos(). Kenapa JSON bukan array in-memory? Dev server me-restart modul saat kamu mengedit file sehingga array in-memory ikut ter-reset, sedangkan file JSON selamat.
// app/todos/data.ts (kerangka, lengkapi sendiri)
import { readFile, writeFile } from "fs/promises";
import { join } from "path";
const FILE = join(process.cwd(), "todos.json");
export type Todo = { id: string; judul: string; selesai: boolean };
export async function getTodos(): Promise<Todo[]> {
// baca FILE; kembalikan [] bila file belum ada (try/catch)
}
export async function saveTodos(todos: Todo[]): Promise<void> {
// tulis JSON.stringify(todos) ke FILE
}Langkah 2: tiga Server Actions
Di actions.ts, tulis tambahTodo, toggleTodo, dan hapusTodo:
// app/todos/actions.ts (kerangka)
"use server";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { getTodos, saveTodos, type Todo } from "./data";
const Skema = z.object({ judul: z.string().min(3, "Judul minimal 3 karakter") });
export async function tambahTodo(_prev: unknown, formData: FormData) {
// 1. validasi Zod → return { error } bila gagal
// 2. buat todo baru (id: crypto.randomUUID()), simpan
// 3. revalidatePath("/todos")
}
export async function toggleTodo(id: string) {
// 1. beri delay 1 detik (agar efek optimistik terlihat)
// 2. balik flag selesai, simpan
// 3. revalidatePath("/todos")
}
export async function hapusTodo(id: string) {
// 1. buang todo dengan id tersebut, simpan
// 2. revalidatePath("/todos")
}Aturannya: semua bertanda "use server", semua mutasi lewat sini (tidak ada API route), dan setiap aksi yang sukses memanggil revalidatePath("/todos").
Langkah 3: form tambah dengan pesan error
AddForm.tsx memakai useActionState (modul 41): tampilkan error validasi dari server tepat di bawah input, tombol disable saat pending, dan kosongkan input setelah sukses. Ini menguji pemahamanmu tentang state hasil action.
Langkah 4: daftar dengan toggle optimistik
TodoList.tsx memakai useOptimistic (modul 42) untuk toggle selesai/belum. Karena toggleTodo punya delay 1 detik, efek instannya akan terlihat jelas: centang langsung berubah, server menyusul. Tambahkan try/catch + router.refresh() untuk rollback bila gagal.
Langkah 5: hapus dengan konfirmasi
Satu tombol hapus per item. Karena hapus tidak bisa di-undo, JANGAN optimistik di sini (ingat aturan modul 42). Tampilkan confirm() bawaan browser dulu, baru panggil hapusTodo bila user setuju.
Langkah 6: uji seperti QA
- Tambah todo kosong → harus muncul error, bukan todo kosong.
- Tambah "ab" (2 karakter) → error Zod "minimal 3 karakter".
- Toggle 5x cepat → UI tetap konsisten, tidak ada flicker aneh.
- Refresh browser → data tetap ada (JSON bekerja).
- Matikan JavaScript di DevTools → form tambah masih berfungsi (progressive enhancement).
Kalau semua lolos, kamu resmi paham Server Actions end-to-end. Kirim kodemu untuk dinilai AI tutor.
Catatan teknis: Kriteria penilaian ada di assignment modul ini: Server Actions untuk semua mutasi, validasi Zod di server, optimistic update saat toggle, dan
revalidatePathsetelah mutasi.
Tantangan
Rencana dulu
Sebelum ngoding, tulis daftar file yang akan kamu buat (mis. app/todos/page.tsx, app/todos/actions.ts) beserta fungsi masing-masing dalam 1 kalimat.
Tugas
Todo App dengan Server Actions
Bangun aplikasi todo lengkap: tambah (validasi Zod), toggle selesai (optimistic), hapus. Semua mutasi via Server Actions. Tulis kode lengkap (actions + komponen) di bawah.
Kriteria penilaian:
- Server Action untuk tambah/toggle/hapus dengan "use server"
- Validasi Zod di server sebelum simpan
- Optimistic update saat toggle
- revalidatePath setelah mutasi
AI tutor akan memeriksa bug, kesalahan syntax, dan memberi saran perbaikan.
Kuis Bab
Uji pemahamanmu: Server Actions & Form
Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".
1.Apa itu Server Action?
2.Di mana validasi keamanan harus dilakukan?
3.Apa fungsi useActionState?
4.Kapan optimistic update TIDAK boleh dipakai?
5.Apa yang dilakukan revalidatePath("/todos")?