Skip to content

Hiểu React Component cơ bản với Rating App

Trong React, mọi thứ đều là component. Lưu ý nhất phần Event Handler.
Component là đơn vị xây dựng UI cơ bản nhất, giúp bạn chia nhỏ giao diện thành các mảnh độc lập, tái sử dụng được, và dễ bảo trì.
Từ một nút bấm nhỏ, một thanh điều hướng, cho đến cả một trang web hoàn chỉnh — tất cả đều được xây dựng từ các component lồng vào nhau.

Component là gì?

Component trong React đơn giản là một hàm JavaScript trả về JSX — một đoạn mô tả giao diện.
Sau đó bạn có thể “nhúng” nó vào bất kỳ component nào khác như một thẻ HTML:
Một vài quy tắc cần nhớ ngay từ đầu:
Tên component phải viết hoa chữ cái đầuRating, không phải rating. React phân biệt component tự định nghĩa với thẻ HTML gốc chính bằng cách này.
Mỗi component nên có một file riêng — đặt trong thư mục components/, tên file trùng với tên component (ví dụ: Rating.jsx).

Render danh sách với .map()

Khi cần render nhiều phần tử lặp lại — ví dụ 5 ngôi sao — bạn dùng .map() để biến một mảng thành danh sách JSX.
Lưu ý:
Prop key là bắt buộc khi render danh sách. React dùng nó để theo dõi từng phần tử khi UI cập nhật. Nếu thiếu, bạn sẽ thấy warning trên console — và có thể gặp bug khó hiểu khi danh sách thay đổi. Dùng giá trị duy nhất, ổn định — ở đây là star (1, 2, 3, 4, 5).
Không dùng index của .map() làm key nếu danh sách có thể bị sắp xếp lại hoặc lọc bớt.
Nhân tiện, ngoài lề một về hàm tạo mảng tự động. Nếu bạn muốn tạo 1 array với các số tuần tự:

Styling Component

Có nhiều cách style trong React. Với component nhỏ như Rating, hai cách phổ biến nhất là:
Inline style — dùng khi style đơn giản, không cần tách file:
External CSS — cách phổ biến nhất, dễ maintain hơn khi dự án lớn:
Lưu ý: trong JSX dùng className thay cho class (vì class là từ khóa trong JavaScript).

CSS Modules

CSS Modules thực ra khá phổ biến trong các dự án React — đặc biệt khi dùng với Vite hoặc Next.js vì được hỗ trợ sẵn, không cần cài thêm gì. Nó nằm giữa “inline style” (quá đơn giản) và Tailwind/styled-components (cần setup thêm). Nhiều team chọn nó vì tránh được xung đột class name mà vẫn viết CSS thuần.
CSS Modules là cách viết CSS riêng cho từng component, trong đó tên class được tự động đổi thành duy nhất khi build — nên không bao giờ bị trùng với component khác, dù bạn đặt tên giống nhau.
Hai điểm khác so với CSS thông thường:
Import như một objectimport styles from './Rating.module.css' trả về một object, mỗi class name là một key. Dùng styles.container thay vì "container".
Tên file phải có .module.css — đây là quy ước để bundler (Vite, webpack) nhận ra và xử lý class scoping tự động. File Rating.css bình thường sẽ không có tính năng này.
Khi build xong, class .star trong Rating.module.css sẽ thành tên kiểu _star_x7k2p_1 — unique, không đụng hàng với .star ở bất kỳ component nào khác.

Event Handler

Đây là phần quan trọng nhất trong bài — nơi component bắt đầu có tương tác.

Cú pháp cơ bản

React dùng camelCase cho tên event, và nhận vào một hàm (không phải chuỗi như HTML thuần):

Lưu ý quan trọng: có () hay không?

Đây là điểm dễ nhầm nhất:
Nếu cần truyền tham số, bọc trong arrow function:
Quy tắc đơn giản để nhớ: nếu cần truyền tham số → bọc trong () =>. Nếu không cần → truyền thẳng tên hàm.
Về bản chất đây là callback function.
Hãy nghĩ theo cách này: onClick chờ bạn truyền vào một hàm để gọi sau — tức là chỉ gọi khi có sự kiện xảy ra, không gọi ngay. Đó là định nghĩa của callback.
Khi cần truyền tham số, bạn không thể viết onClick={handleClick(star)}handleClick(star) gọi hàm ngay lập tức và trả về kết quả — thay vì truyền một hàm. Lúc này onClick nhận được undefined thay vì một callback.
Giải pháp là bọc trong một arrow function rỗng:
Cơ chế này không phải đặc thù của React — đây là JavaScript thuần.
Hoàn toàn tương đương với addEventListener trong Vanilla JS:
Cùng một pattern, chỉ khác cú pháp. addEventListener cũng chờ nhận vào một hàm callback — truyền thẳng tên hàm nếu không có args, bọc trong arrow function nếu cần truyền args vào.

Ví dụ thực tế với Rating

rating_app_annotated_regions.svg
Ở đây bạn thấy ba event phổ biến:
onClick — xử lý click chuột
onMouseEnter — chuột di vào phần tử
onMouseLeave — chuột rời khỏi phần tử
Tất cả đều nhận arrow function vì cần truyền tham số vào hàm xử lý.

Lưu ý Best Practices

Đặt tên hàm xử lý event có prefix handle — ví dụ handleClick, handleSubmit, handleChange. Giúp dễ phân biệt với các hàm logic khác.
Tách hàm handler ra ngoài JSX — đừng viết logic phức tạp trực tiếp trong onClick={...}. Khó đọc và khó debug.
Một component nên làm một việc — nếu component đang xử lý quá nhiều thứ, hãy cân nhắc tách nhỏ ra.

Tóm tắt

Trong bài này, bạn đã nắm được:
Component là hàm trả về JSX, tên phải viết hoa, mỗi component nên có một file riêng.
Render danh sách dùng .map(), luôn kèm prop key với giá trị duy nhất và ổn định.
Styling có thể dùng inline style hoặc external CSS với className.
Event Handler nhận vào một hàm (không gọi trực tiếp), dùng arrow function khi cần truyền tham số.
Bước tiếp theo tự nhiên từ đây là State — cách React lưu và cập nhật dữ liệu bên trong component (ví dụ: lưu lại ngôi sao nào đang được chọn). Sau đó là Props — cách truyền dữ liệu từ component cha xuống component con. Hai khái niệm này sẽ làm cho Rating của bạn thực sự hoạt động.
Want to print your doc?
This is not the way.
Try clicking the ··· in the right corner or using a keyboard shortcut (
CtrlP
) instead.