Langkau ke kandungan
WANCODE
EN

Bina Pengurus Tugasan

25 minitPertengahanReact

Dalam pelajaran ini

  • Rancang state aplikasi: apa yang mesti disimpan, dan apa yang boleh dikira
  • Tambah, kemas kini dan buang item dalam array objek tanpa mengubahnya secara terus (mutate)
  • Gabungkan borang, senarai, komposisi, paparan bersyarat dan effect dalam satu aplikasi

Idea utama

Aplikasi sebenar ialah idea-idea kecil yang sama, digabungkan: satu array tugasan dalam state, borang yang menambah ke dalamnya, component anak yang melaporkan klik ke atas, nilai yang dikira semasa render, dan satu effect yang menyimpan semuanya.

Masa untuk membina sesuatu yang anda boleh guna setiap hari. Sebelum menulis kod, developer yang baik menentukan state apa yang aplikasi perlukan. Tanya: "Apa yang berubah dari semasa ke semasa, dan bolehkah saya mengiranya daripada sesuatu yang lain?"

tasks (state)
Array seperti [{ id: 1712, title: "Beli susu", done: false }]. Satu-satunya sumber kebenaran.
title (state)
Apa yang sedang ditaip dalam input — input terkawal.
filter (state)
"all", "active" atau "done".
visible, remaining (derived)
Dikira daripada tasks dan filter semasa render. Bukan state, tiada effect.

Mengemas kini array tanpa mutate

Jangan push ke dalam state atau ubah objek tugasan secara terus — React membandingkan rujukan (reference), jadi ia tidak akan perasan. Sentiasa bina array baharu:

JSX
// add
setTasks([...tasks, { id: Date.now(), title, done: false }]);

// toggle one: copy it with the opposite "done"
setTasks(tasks.map((t) => (t.id === id ? { ...t, done: !t.done } : t)));

// delete one
setTasks(tasks.filter((t) => t.id !== id));

Date.now() (milisaat sejak 1970) ialah id ringkas untuk aplikasi peribadi yang kecil, selagi anda tidak mencipta dua tugasan dalam milisaat yang sama. Aplikasi lebih besar menggunakan id daripada pangkalan data atau crypto.randomUUID().

Kira, jangan salin

JSX
const visible = tasks.filter((t) =>
  filter === "active" ? !t.done : filter === "done" ? t.done : true
);
const remaining = tasks.filter((t) => !t.done).length;

Simpan dengan satu effect

localStorage hanya menyimpan string, jadi guna JSON.stringify untuk menyimpan dan JSON.parse untuk memuatkan. Muat sekali dengan memberi function kepada useState; simpan setiap kali tasks berubah.

JSX
const [tasks, setTasks] = useState(() => {
  try {
    return JSON.parse(localStorage.getItem("wancode-tasks")) ?? [];
  } catch {
    return [];
  }
});

useEffect(() => {
  localStorage.setItem("wancode-tasks", JSON.stringify(tasks));
}, [tasks]);

Storage pratonton pelajaran ini dikekalkan antara larian, jadi tugasan yang anda (atau semakan) tambah masih ada pada kali seterusnya — itu tandanya penyimpanan berfungsi! Semakan menambah tugasan dengan nama rawak dan hanya memeriksa tugasan itu.

  • Kekalkan nama-nama ini supaya semakan boleh menjumpainya: #new-task dalam form.add-form, ul.tasks yang mengandungi li.task (tambah class done apabila siap), checkbox dan butang .delete dalam setiap item, butang penapis dengan data-filter="all" | "active" | "done", dan .remaining.

Lengkapkan handleSubmit: trim tajuk yang ditaip, abaikan jika kosong, jika tidak tambah { id: Date.now(), title, done: false } di hujung tasks dan kosongkan input.

Semakan

  • Submit menambah tugasan ke dalam senarai
  • Input dikosongkan selepas menambah
  • Tugasan kosong diabaikan

Uji kefahaman

Q1

Kenapa tasks.push(newTask); setTasks(tasks); tidak mengemas kini skrin dengan betul?

Q2

Apakah cara terbaik untuk tahu berapa tugasan yang tinggal?

Q3

Kenapa kita guna JSON.stringify sebelum localStorage.setItem?

Apa yang anda pelajari

  • Rancang state dahulu: simpan yang minimum (tasks, title, filter), kira yang selebihnya (visible, remaining).
  • Kemas kini array tanpa mutate: spread untuk tambah, map untuk ubah satu, filter untuk buang.
  • Anak melaporkan event ke atas dengan prop callback; induk memiliki data.
  • Satu effect + JSON.stringify menyimpan ke localStorage; initialiser useState yang lazy memuatkannya semula.
Pratonton

Output konsol daripada kod anda akan dipaparkan di sini.

Langkah 1 daripada 3