tinbc tinbc

Hướng dẫn React cơ bản qua một dự án thực tế

Code Dạo6 phút đọc1 lượt xem
Hướng dẫn React cơ bản qua một dự án thực tế

Đọc tài liệu React mà chưa viết dòng nào thường khiến bạn rối: component, props, state, hook… nghe trừu tượng. Cách hiệu quả hơn là dựng một app thật rồi học khái niệm ngay khi chạm tới. Bài này dẫn bạn làm một app to-do (danh sách việc cần làm) hoàn chỉnh — mỗi khái niệm React xuất hiện đúng lúc bạn cần dùng nó, nên nó “dính” luôn thay vì trôi đi.

Cần nền JavaScript cơ bản trước; nếu chưa vững, xem học JavaScript từ con số 0 rồi quay lại.

React là gì và giải quyết vấn đề gì?

React là một thư viện JavaScript để dựng giao diện người dùng bằng cách chia màn hình thành các component (khối tái sử dụng) và tự động cập nhật giao diện khi dữ liệu thay đổi. Vấn đề nó giải quyết: với JavaScript thuần, mỗi lần dữ liệu đổi bạn phải tự tay tìm phần tử HTML và sửa — rối và dễ sai. React lo việc “vẽ lại” giúp bạn; bạn chỉ mô tả “giao diện trông thế nào ứng với dữ liệu này”.

Ý tưởng cốt lõi: giao diện = một hàm của dữ liệu. Dữ liệu (state) đổi → React tự vẽ lại đúng chỗ.

Bước 1 — Tạo dự án React

Cách nhanh nhất để có môi trường React chạy được là dùng Vite. Mở terminal và gõ:

npm create vite@latest my-todo -- --template react
cd my-todo
npm install
npm run dev

Mở đường link báo trong terminal (thường http://localhost:5173) là thấy trang mẫu. Mở thư mục bằng VS Code (xem hướng dẫn cài VS Code) và tìm file src/App.jsx — đây là nơi ta làm việc.

Bước 2 — Component và JSX

Một component trong React là một hàm trả về giao diện; cú pháp “HTML trong JavaScript” đó gọi là JSX. Xoá nội dung App.jsx và viết lại:

function App() {
  return (
    <div>
      <h1>Việc cần làm</h1>
      <p>App to-do đầu tiên của tôi</p>
    </div>
  );
}
export default App;

Lưu lại, trang tự cập nhật. Vài điều cần biết về JSX: chỉ được trả về một thẻ gốc (nên bọc trong <div>), dùng className thay cho class, và chèn biến JavaScript bằng {}: <h1>{title}</h1>.

Bước 3 — State: lưu danh sách việc với useState

State là dữ liệu có thể thay đổi của component; để React vẽ lại khi nó đổi, ta khai báo bằng hook useState. Thêm danh sách việc và ô nhập:

import { useState } from "react";

function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: "Học React" },
    { id: 2, text: "Uống cà phê" },
  ]);
  const [text, setText] = useState("");

  return (
    <div>
      <h1>Việc cần làm</h1>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>{task.text}</li>
        ))}
      </ul>
    </div>
  );
}
export default App;

Giải thích: useState(...) trả về giá trị hiện tại (tasks) và hàm để đổi nó (setTasks). Mỗi việc là một object có id riêng — ta dùng id làm key khi .map(), ổn định hơn dùng vị trí (index) vì khi xoá một mục ở giữa, index bị xô lệch còn id thì không. Đây là lý do phải nắm map của JavaScript trước.

Bước 4 — Thêm việc mới (xử lý sự kiện)

Để thêm việc, ta cập nhật state bằng hàm set — không bao giờ sửa mảng trực tiếp, mà tạo mảng mới:

function addTask() {
  if (text.trim() === "") return;                 // bỏ qua nếu rỗng
  setTasks([...tasks, { id: Date.now(), text }]); // tạo mảng mới + việc mới có id duy nhất
  setText("");                                    // xoá ô nhập
}

Rồi gắn vào nút bấm trong JSX (đặt ngay cạnh <input>): <button onClick={addTask}>Thêm</button>.

Điểm mấu chốt: setTasks([...tasks, ...]) tạo mảng mới (dấu ... sao chép mảng cũ) rồi thêm phần tử. React so sánh state mới với cũ để biết cần vẽ lại — nên phải thay bằng giá trị mới, không sửa tại chỗ. Ta lấy Date.now() (mốc thời gian) làm id duy nhất cho mỗi việc mới.

Bước 5 — Xoá việc

Xoá cũng theo nguyên tắc tạo mảng mới, dùng .filter() để giữ lại mọi mục trừ mục cần xoá:

function removeTask(id) {
  setTasks(tasks.filter((task) => task.id !== id));  // giữ lại mọi việc TRỪ việc có id này
}

Gắn nút xoá vào mỗi dòng: <li key={task.id}>{task.text} <button onClick={() => removeTask(task.id)}>x</button></li>. Vậy là đủ chức năng: thêm, hiển thị, xoá — giao diện tự cập nhật mỗi khi danh sách đổi.

Bước 6 — Ghép lại: App.jsx hoàn chỉnh

Đây là toàn bộ file src/App.jsx sau các bước trên — copy đè để đối chiếu nếu bạn lạc chỗ đặt hàm:

import { useState } from "react";

function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: "Học React" },
    { id: 2, text: "Uống cà phê" },
  ]);
  const [text, setText] = useState("");

  function addTask() {
    if (text.trim() === "") return;
    setTasks([...tasks, { id: Date.now(), text }]);
    setText("");
  }

  function removeTask(id) {
    setTasks(tasks.filter((task) => task.id !== id));
  }

  return (
    <div>
      <h1>Việc cần làm</h1>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <button onClick={addTask}>Thêm</button>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.text} <button onClick={() => removeTask(task.id)}>x</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
export default App;

Lưu ý vị trí: các hàm (addTask, removeTask) nằm bên trong function App(), trước câu lệnh return.

Bước 7 — Props: tách một component con

Props là dữ liệu truyền từ component cha xuống component con để nó hiển thị — giống tham số của hàm. Hãy tách mỗi dòng việc thành component TaskItem để thấy props hoạt động:

function TaskItem({ task, onRemove }) {
  return (
    <li>
      {task.text} <button onClick={() => onRemove(task.id)}>x</button>
    </li>
  );
}

Rồi trong App, thay phần .map(...) bằng:

{tasks.map((task) => (
  <TaskItem key={task.id} task={task} onRemove={removeTask} />
))}

taskonRemove chính là props: App (cha) truyền dữ liệu (task) và hàm xử lý (onRemove) xuống TaskItem (con). Tách component như vậy giúp code gọn và tái sử dụng — đây là cách React tổ chức giao diện lớn.

Lưu ý: sau bước này, phần .map(...) trong App của bạn đã khác khối ở Bước 6 (giờ render <TaskItem /> thay cho <li> trực tiếp) — nhớ giữ định nghĩa TaskItem ngoài function App. Phần state và hàm còn lại vẫn như Bước 6.

Lỗi thường gặp của người mới

Vài lỗi hay vướng khi mới học React:

  • Quên key khi map — React cảnh báo trong console; luôn thêm key duy nhất.
  • Sửa state trực tiếp (tasks.push(...)) — màn hình không cập nhật; phải dùng setTasks với mảng mới.
  • Quên import useState — báo lỗi “useState is not defined”.
  • Đọc thông báo lỗi để sửa nhanh: xem cách đọc lỗi và debug cho người mới.

Bước tiếp theo cụ thể

Bạn vừa dựng xong một app React có state và props thật — những viên gạch nền của hầu hết ứng dụng React. Hôm nay hãy tự thêm một tính năng nhỏ: nút “đánh dấu đã xong” (gợi ý: thêm trạng thái done cho mỗi việc và đổi kiểu chữ khi xong). Khi quen tay, học tiếp useEffect (chạy việc phụ khi state đổi) và tách giao diện thành nhiều component con — đó là chặng tiếp theo tự nhiên của React.

Chia sẻ:
0.0 0 lượt đánh giá

Câu hỏi thường gặp

Cần biết gì trước khi học React?

Cần nắm JavaScript cơ bản: biến, hàm, mảng (đặc biệt map), và arrow function. React là thư viện JavaScript nên không có nền JS sẽ rất chật vật. Không cần biết trước framework nào khác. Nếu JS còn yếu, hãy học JS trước rồi quay lại React.

Component và props khác nhau thế nào?

Component là một khối giao diện tái sử dụng được (như một hàm trả về HTML). Props là dữ liệu bạn truyền từ component cha xuống component con để nó hiển thị — giống tham số của hàm. Component định nghĩa ‘trông thế nào’, props quyết định ‘hiển thị dữ liệu gì’.

Vì sao phải dùng useState thay vì gán biến thường?

Vì React chỉ vẽ lại giao diện khi ‘state’ thay đổi qua hàm set của useState. Nếu bạn gán biến thường, dữ liệu đổi nhưng màn hình không cập nhật. useState báo cho React biết ‘dữ liệu đã đổi, hãy vẽ lại’ — đó là cơ chế cốt lõi của React.

Code Dạo

Code Dạo

Lang thang khắp thế giới code và AI, gặp gì hay ho là viết lại cho mọi người cùng nghịch. Với mình, lập trình nên vui như chơi game — và mình sẵn lòng chỉ bạn từng nước đi.

Bài liên quan

Bài 3: Chuỗi (string) và thao tác văn bản trong Python
Lập trình

Bài 3: Chuỗi (string) và thao tác văn bản trong Python

Bài 3 series Python cho người mới (bài học 30 phút): làm chủ chuỗi và các thao tác văn bản hay dùng nhất qua một chương trình đếm từ và ký tự tự viết — kèm bài tập gõ code, lỗi thường gặp và code mang về.

1 lượt xem
Cách đọc lỗi và debug cho người mới học code
Lập trình

Cách đọc lỗi và debug cho người mới học code

Gặp lỗi đỏ lòm là chuyện thường khi học code — quan trọng là biết đọc và sửa. Hướng dẫn đọc thông báo lỗi, ba loại lỗi hay gặp, và quy trình debug từng bước cho người mới.

Bài 3: HTML — cấu trúc một trang web
Lập trình

Bài 3: HTML — cấu trúc một trang web

Bài 3 series Web cơ bản (bài học 30 phút): hiểu thẻ HTML và khung chuẩn của một trang, tự tay dựng khung trang cá nhân — kèm bài thực hành, lỗi thường gặp và file mang về.