Bài 4. State và hook

State làm cho giao diện "sống": khi dữ liệu đổi, giao diện tự cập nhật. Hook là các hàm đặc biệt để dùng state và hiệu ứng.

45 phútTrung cấp
Bạn sẽ học được
  • Dùng useState lưu trạng thái
  • Dùng useEffect cho tác vụ phụ như gọi API
  • Xử lý sự kiện và biểu mẫu có kiểm soát
  • Nâng state lên component cha
Thuật ngữ cần biết
State
Dữ liệu riêng của component; thay đổi sẽ vẽ lại giao diện.
Hook
Hàm bắt đầu bằng use cho phép dùng tính năng React trong component hàm.
Effect
Việc chạy sau khi vẽ: gọi API, đặt tiêu đề, đăng ký sự kiện.
Controlled input
Ô nhập có giá trị do state quản lý.

useState

import { useState } from "react";

function BoDem() {
  const [n, setN] = useState(0);
  return (
    <div>
      <p>Đã bấm: {n}</p>
      <button onClick={() => setN(n + 1)}>Tăng</button>
      <button onClick={() => setN(0)}>Đặt lại</button>
    </div>
  );
}

Không sửa trực tiếp n; luôn gọi hàm setN. Với đối tượng và mảng, tạo bản sao mới: setDs([...ds, moi]).

Biểu mẫu có kiểm soát

function Loc() {
  const [tu, setTu] = useState("");
  const ds = ["Python", "React", "Git"];
  const kq = ds.filter(x => x.toLowerCase().includes(tu.toLowerCase()));
  return (
    <>
      <input value={tu} onChange={e => setTu(e.target.value)} placeholder="Tìm..." />
      <ul>{kq.map(x => <li key={x}>{x}</li>)}</ul>
    </>
  );
}

useEffect gọi API

import { useState, useEffect } from "react";

function BaiViet() {
  const [ds, setDs] = useState([]);
  const [dangTai, setDangTai] = useState(true);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts?_limit=5")
      .then(r => r.json())
      .then(d => { setDs(d); setDangTai(false); });
  }, []);            // [] = chỉ chạy một lần khi hiện ra

  if (dangTai) return <p>Đang tải...</p>;
  return <ul>{ds.map(b => <li key={b.id}>{b.title}</li>)}</ul>;
}

Nâng state lên

function Cha() {
  const [mau, setMau] = useState("xanh");
  return (
    <>
      <ChonMau mau={mau} doi={setMau} />
      <HienMau mau={mau} />
    </>
  );
}

Khi hai component cần dùng chung dữ liệu, đặt state ở component cha gần nhất rồi truyền xuống.

Tình huống: Giỏ hàng nhỏ

State là mảng sản phẩm trong giỏ. Bấm "Thêm" gọi setGio([...gio, sp]); tổng tiền tính từ gio.reduce(...); giao diện tự cập nhật, không cần chạm vào DOM.

Mẹo hay

Cài React Developer Tools (tiện ích trình duyệt) để xem cây component, props và state.

Lưu ý

Không gọi hook trong điều kiện, vòng lặp hay hàm lồng; chỉ gọi ở cấp cao nhất của component. Quên mảng phụ thuộc trong useEffect dễ gây vòng lặp vô hạn.

Thực hành
  1. Làm bộ đếm có nút tăng, giảm, đặt lại.
  2. Làm ô tìm kiếm lọc danh sách khóa học.
  3. Tải danh sách bài viết từ API và hiển thị trạng thái Đang tải, Lỗi.
Tóm tắt bài học
  • State thay đổi thì giao diện cập nhật.
  • useEffect cho tác vụ phụ, mảng phụ thuộc điều khiển khi nào chạy.
  • Dữ liệu chung đặt ở component cha.