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.
const Rating = () => {
return (
<div>
<h2>Rate Your Experience</h2>
</div>
);
};
Sau đó bạn có thể “nhúng” nó vào bất kỳ component nào khác như một thẻ HTML:
function App() {
return (
<div>
<Rating />
</div>
);
}
Một vài quy tắc cần nhớ ngay từ đầu:
Tên component phải viết hoa chữ cái đầu — Rating, 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). // components/Rating.jsx
const Rating = () => {
return (
<div>
<h2>Rate Your Experience</h2>
</div>
);
};
export default Rating;
// App.jsx
import Rating from './components/Rating';
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.
const Rating = () => {
const stars = [1,2,3,4,5]
return (
<div className="rating-container">
<h2>Rate Your Experience</h2>
<div className="stars">
{stars.map((star) => (
<span key={star} className="star">
{'\u2605'}
</span>
))}
</div>
</div>
);
};
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ự:
const stars = Array.from({ length: 5 }, (_, i) => i + 1);
// hàm Array.from() tạo array mới từ array-like object hoặc iterable
Array.from([1, 2, 3]); // [1, 2, 3] - từ array
Array.from("hello"); // ['h', 'e', 'l', 'l', 'o'] - từ string
// Array.from sẽ tạo array từ object { length: 5 } với 5 phần tử 'undefined'
Array.from({ length: 5 }); // [undefined, undefined, undefined, undefined, undefined]
// (_, i) => i + 1)
// là map function (tham số thứ 2 của Array.from)
// _ = current value (bỏ qua vì là undefined)
// i = index (0, 1, 2, 3, 4)
// Return i + 1 = (1, 2, 3, 4, 5)
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:
// Hai dấu {{ }}: ngoài là JSX, trong là CSS object
<div style={{ textAlign: 'center', padding: '20px' }}>
External CSS — cách phổ biến nhất, dễ maintain hơn khi dự án lớn:
import './Rating.css';
<div className="rating-container">
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.
/* Rating.module.css */
.container {
text-align: center;
padding: 20px;
}
.stars {
display: flex;
gap: 8px;
justify-content: center;
}
.star {
font-size: 32px;
color: #ccc;
cursor: pointer;
}
.star:hover {
color: #f5a623;
}
/* Rating.jsx */
import styles from './Rating.module.css';
const Rating = () => {
const stars = Array.from({ length: 5 }, (_, i) => i + 1);
return (
<div className={styles.container}>
<h2>Rate Your Experience</h2>
<div className={styles.stars}>
{stars.map((star) => (
<span key={star} className={styles.star}>
{'\u2605'}
</span>
))}
</div>
</div>
);
};
Hai điểm khác so với CSS thông thường:
Import như một object — import 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):
// HTML thuần
<button onclick="handleClick()">Click</button>
// JSX
<button onClick={handleClick}>Click</button>
Lưu ý quan trọng: có () hay không?
Đây là điểm dễ nhầm nhất:
// ✅ Đúng — truyền hàm vào, chỉ gọi khi click
<button onClick={handleClick}>Click</button>
// ❌ Sai — gọi hàm ngay lúc render, không phải lúc click
<button onClick={handleClick()}>Click</button>
Nếu cần truyền tham số, bọc trong arrow function:
// ✅ Đúng — dùng arrow fn để truyền args