Langkau ke kandungan
WANCODE
EN

State: Component Yang Mengingat

18 minitPertengahanReact

Dalam pelajaran ini

  • Terangkan kenapa variable biasa tidak boleh mengemas kini skrin
  • Cipta state dengan useState dan kemas kini dengan setter-nya
  • Kemas kini array dan objek dengan mencipta yang baharu, bukan memutasi
  • Guna kemas kini berfungsi bila nilai seterusnya bergantung pada nilai sebelumnya

Idea utama

State ialah data yang diingati oleh component antara render. Bila anda panggil setter, React menjalankan component anda semula dengan nilai baharu dan mengemas kini skrin.

Props datang dari induk. Tetapi sesetengah data milik component itu sendiri dan berubah semasa pengguna berinteraksi: kaunter, senarai pesanan, sama ada menu dibuka. Itulah state.

Kenapa variable biasa tak berfungsi

Component ialah function. Setiap kali React me-render-nya, function itu berjalan dari atas — jadi let cups = 0 bermula pada 0 setiap kali render. Dan menukar variable tempatan tidak memberitahu React apa-apa, jadi ia tidak re-render. Variable itu berubah; skrin tidak.

Lupa, dan React tidak diberitahu

JSX
function Counter() {
  let cups = 0;

  function add() {
    cups = cups + 1; // changes, but no re-render
  }

  return <button onClick={add}>{cups}</button>;
}

Diingati, dan mencetuskan re-render

JSX
import { useState } from "react";

function Counter() {
  const [cups, setCups] = useState(0);

  function add() {
    setCups(cups + 1); // new value + re-render
  }

  return <button onClick={add}>{cups}</button>;
}
useState(initial)
Sebuah hook — function khas React yang namanya bermula dengan use. Ia memulangkan sepasang: nilai semasa dan function untuk mengubahnya.
const [cups, setCups]
Destructuring array. Namakan apa sahaja yang anda suka; kebiasaannya thing dan setThing.
Re-render
React memanggil function component anda sekali lagi. Kali ini useState memulangkan nilai baharu, dan React mengemas kini hanya bahagian DOM yang berubah.
Klik → setter → React menjalankan semula component → DOM dikemas kini dengan perbezaannya.

Peraturan hook

Panggil useState di peringkat atas component anda — bukan di dalam if, gelung atau function bersarang. React membezakan hook mengikut susunan ia dipanggil, jadi susunan itu mesti sama setiap kali render.

Peraturan 1: jangan mutasi state

React menentukan sama ada perlu re-render dengan menyemak sama ada nilai baharu itu nilai yang berbeza (ia guna Object.is). Kalau anda push ke dalam array yang sama dan hantar semula array yang sama itu, React nampak "tiada apa berubah" dan langkau kemas kini. Sentiasa cipta array atau objek yang baharu.

Mutasi (tiada re-render)

JSX
orders.push("Order #3");
setOrders(orders); // same array!

user.name = "Siti";
setUser(user);     // same object!

Nilai baharu (re-render)

JSX
setOrders([...orders, "Order #3"]);

setUser({ ...user, name: "Siti" });

setOrders(orders.filter((o) => o !== "Order #1"));

Peraturan 2: bergantung pada nilai sebelum? Hantar function

Dalam satu render, cups ialah snapshot — nombor yang tetap. Memanggil setter tidak mengubahnya; ia meminta React membuat render baharu. Jadi kalau anda beratur beberapa kemas kini daripada snapshot yang sama, semuanya mengira daripada nombor lama yang sama. Hantar function updater sebaliknya dan React akan memberinya nilai terkini.

Tambah 1, bukan 3 (cups tetap 0)

JSX
function addThree() {
  setCups(cups + 1); // 0 + 1
  setCups(cups + 1); // 0 + 1
  setCups(cups + 1); // 0 + 1
}

Tambah 3

JSX
function addThree() {
  setCups((c) => c + 1); // 0 → 1
  setCups((c) => c + 1); // 1 → 2
  setCups((c) => c + 1); // 2 → 3
}

Masalah snapshot yang sama muncul dengan pemasa: callback setTimeout mengingati cups daripada render di mana ia dicipta. Anda akan membaiki masalah itu dalam latihan 2.

Klik +1 cup dan buka Console: variable itu naik, tetapi nombor besar kekal 0.

Gantikan let cups = 0 dengan state: const [cups, setCups] = useState(0). Kemudian ubah addCup supaya memanggil setCups(cups + 1). Buat perkara yang sama di dalam addCupLater buat masa ini (setCups(cups + 1) di dalam timeout) — anda akan melihatnya semula dalam latihan seterusnya.

Semakan

  • Kaunter bermula pada 0
  • Klik "+1 cup" mengemas kini skrin

Uji kefahaman

Q1

Kenapa let count = 0; … count++ tidak mengemas kini skrin dalam component?

Q2

count ialah 0. Satu klik menjalankan setCount(count + 1); setCount(count + 1);. Berapakah count selepas re-render?

Q3

Bagaimana anda patut menambah item ke dalam array dalam state?

Apa yang anda pelajari

  • const [value, setValue] = useState(initial) memberi component ingatan antara render.
  • Memanggil setter menjalankan semula component dengan nilai baharu; React kemudian mengemas kini DOM.
  • Jangan mutasi state — buat array/objek baharu dengan spread: [...list, x], { ...obj, key: v }.
  • Bila nilai seterusnya bergantung pada nilai sebelumnya, guna setValue((prev) => …).
Pratonton

Output konsol daripada kod anda akan dipaparkan di sini.

Langkah 1 daripada 3