Cơ bảnKiến thức cơ bản

Component trong React: Function Component vs Class Component

8 phút đọc0 lượt xem
#component react#function component#class component#jsx là gì#props react#react cơ bản

Component trong React: Function Component vs Class Component

Khi học React, khái niệm đầu tiên bạn cần nắm vững chính là Component. Mọi ứng dụng React đều được xây dựng từ những component nhỏ ghép lại với nhau — từ một nút bấm đơn giản cho đến toàn bộ trang web.

Trong bài viết này, chúng ta sẽ tìm hiểu component là gì, cách viết JSX, và quan trọng nhất là sự khác biệt giữa Function Component (cách viết hiện đại) và Class Component (cách viết truyền thống), kèm theo nhiều ví dụ code thực tế.

Component trong React là gì?

Hãy tưởng tượng bạn đang xây một trang web tin tức. Trên trang đó có:

  • Thanh điều hướng ở trên cùng (Header)
  • Danh sách thẻ bài viết (ArticleCard)
  • Thanh bên với bài viết đề xuất (Sidebar)
  • Phần chân trang (Footer)

Trong React, mỗi phần trên là một component — một khối UI độc lập, có thể tái sử dụng. Thay vì viết toàn bộ trang trong một file HTML khổng lồ, bạn chia nhỏ thành các component và ghép lại.

Tại sao dùng component?

  • Tái sử dụng: Tạo component ArticleCard một lần, dùng lại nhiều lần với dữ liệu khác nhau
  • Dễ bảo trì: Sửa lỗi ở một chỗ, toàn bộ nơi dùng component đó đều được cập nhật
  • Làm việc nhóm: Mỗi thành viên có thể phụ trách một component riêng biệt

Nếu bạn chưa biết React là gì, hãy đọc bài giới thiệu trước để có nền tảng tốt hơn.

JSX là gì? Cú pháp đặc biệt của React

Khi viết component React, bạn sẽ dùng JSX — một cú pháp mở rộng cho phép viết "HTML bên trong JavaScript". Đây là ví dụ đơn giản nhất:

function Greeting() {
  return <h1>Xin chào, VietCode!</h1>;
}

Trình duyệt không hiểu JSX trực tiếp. Công cụ Babel sẽ chuyển đổi nó thành JavaScript thuần:

// Sau khi Babel biên dịch
function Greeting() {
  return React.createElement('h1', null, 'Xin chào, VietCode!');
}

Vì vậy, JSX chỉ là "đường tắt" giúp code dễ đọc hơn — bên dưới vẫn là JavaScript thông thường.

Sự khác biệt giữa HTML và JSX

HTML JSX Lý do
class="container" className="container" class là từ khóa trong JavaScript
<img src="..."> <img src="..." /> Tất cả thẻ đều phải được đóng
onclick="fn()" onClick={fn} Sự kiện viết theo camelCase
style="color: red" style={{ color: 'red' }} Style là một object JavaScript
<!-- comment --> {/* comment */} Cú pháp comment trong JSX

Các quy tắc cơ bản của JSX

Quy tắc 1: Luôn có một phần tử gốc duy nhất

// Sai — Hai phần tử ngang hàng ở ngoài cùng
function Wrong() {
  return (
    <h1>Tiêu đề</h1>
    <p>Nội dung</p>
  );
}

// Đúng — Bọc trong div
function Correct() {
  return (
    <div>
      <h1>Tiêu đề</h1>
      <p>Nội dung</p>
    </div>
  );
}

// Đúng — Dùng Fragment (<>) để tránh div thừa
function AlsoCorrect() {
  return (
    <>
      <h1>Tiêu đề</h1>
      <p>Nội dung</p>
    </>
  );
}

Quy tắc 2: Nhúng JavaScript bằng dấu ngoặc nhọn {}

function UserCard() {
  const name = "Nguyễn Minh";
  const age = 22;
  const isStudent = true;

  return (
    <div>
      <h2>{name}</h2>
      <p>Tuổi: {age}</p>
      <p>Trạng thái: {isStudent ? "Sinh viên" : "Đi làm"}</p>
    </div>
  );
}

Function Component — Cách viết hiện đại

Function Component là cách viết component dưới dạng một hàm JavaScript thông thường. Đây là cách viết được khuyến nghị trong React hiện đại (từ năm 2019 đến nay).

Nếu bạn đã hiểu hàm trong JavaScript và các cú pháp mới trong ES6 JavaScript như arrow function, destructuring, thì viết Function Component sẽ rất tự nhiên.

Cú pháp cơ bản

// Khai báo bằng từ khóa function
function Welcome() {
  return <h1>Xin chào từ VietCode!</h1>;
}

// Hoặc dùng arrow function (kết quả như nhau)
const Welcome = () => {
  return <h1>Xin chào từ VietCode!</h1>;
};

// Arrow function rút gọn (khi chỉ return một dòng)
const Welcome = () => <h1>Xin chào từ VietCode!</h1>;

Tên component bắt buộc phải bắt đầu bằng chữ hoa (PascalCase). React phân biệt <Welcome /> (component) với <welcome /> (thẻ HTML không tồn tại).

Ví dụ thực tế: Thẻ bài viết

function ArticleCard() {
  return (
    <div className="article-card">
      <img src="/thumbnail.jpg" alt="Ảnh thumbnail bài viết" />
      <div className="card-content">
        <h3>React là gì? Học React từ đâu?</h3>
        <p>React là thư viện JavaScript phổ biến nhất để xây dựng giao diện web...</p>
        <a href="/articles/react-la-gi" className="read-more">
          Đọc thêm →
        </a>
      </div>
    </div>
  );
}

Function Component với state (dùng Hooks)

Từ React 16.8, bạn có thể thêm trạng thái (state) vào Function Component nhờ Hooks. Đây là lý do Function Component trở thành lựa chọn duy nhất trong React hiện đại:

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // state ban đầu là 0

  return (
    <div>
      <p>Bạn đã nhấn: <strong>{count}</strong> lần</p>
      <button onClick={() => setCount(count + 1)}>
        Nhấn vào đây
      </button>
    </div>
  );
}

Class Component — Cách viết truyền thống

Class Component sử dụng cú pháp class của ES6, kế thừa từ React.Component. Trước khi React Hooks ra đời (năm 2019), đây là cách duy nhất để có state và lifecycle trong component.

Cú pháp cơ bản

import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Xin chào từ VietCode!</h1>;
  }
}

Phương thức render() là bắt buộc — đây là nơi bạn viết JSX sẽ được hiển thị trên màn hình.

Class Component với state

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props); // Bắt buộc khi dùng constructor
    this.state = {
      count: 0
    };
    // Phải bind 'this' thủ công cho event handler
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Bạn đã nhấn: <strong>{this.state.count}</strong> lần</p>
        <button onClick={this.handleClick}>
          Nhấn vào đây
        </button>
      </div>
    );
  }
}

So với Function Component, cùng một chức năng nhưng code Class Component dài hơn và phức tạp hơn đáng kể.

So sánh Function Component vs Class Component

Để thấy rõ sự khác biệt, hãy xem cùng một component được viết theo cả hai cách:

// ===== Cách viết hiện đại: Function Component =====
import { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => setUser(data));
  }, [userId]);

  if (!user) return <p>Đang tải...</p>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  );
}
// ===== Cách viết truyền thống: Class Component =====
import React, { Component } from 'react';

class UserProfile extends Component {
  constructor(props) {
    super(props);
    this.state = { user: null };
  }

  componentDidMount() {
    fetch(`/api/users/${this.props.userId}`)
      .then(res => res.json())
      .then(data => this.setState({ user: data }));
  }

  componentDidUpdate(prevProps) {
    if (prevProps.userId !== this.props.userId) {
      fetch(`/api/users/${this.props.userId}`)
        .then(res => res.json())
        .then(data => this.setState({ user: data }));
    }
  }

  render() {
    const { user } = this.state;
    if (!user) return <p>Đang tải...</p>;

    return (
      <div>
        <h2>{user.name}</h2>
        <p>Email: {user.email}</p>
      </div>
    );
  }
}

Cùng một chức năng, nhưng Function Component ngắn hơn và dễ hiểu hơn nhiều!

Bảng so sánh chi tiết

Tiêu chí Function Component Class Component
Cú pháp Hàm đơn giản Class kế thừa (phức tạp hơn)
Số dòng code Ít hơn 30–50% Nhiều hơn
Quản lý state useState Hook this.state + setState
Lifecycle useEffect Hook componentDidMount, v.v.
Từ khóa this Không cần Cần (dễ gây lỗi binding)
Tái sử dụng logic Custom Hooks (dễ) HOC / render props (phức tạp)
React Server Components Hỗ trợ Không hỗ trợ
Khuyến nghị 2024+ Nên dùng Chỉ dùng cho code cũ

Kết luận: Từ năm 2019 trở đi, React chính thức khuyến nghị dùng Function Component cho tất cả code mới. Class Component vẫn hoạt động bình thường, nhưng bạn không cần viết mới nữa.

Props — Truyền dữ liệu giữa các Component

Props (viết tắt của Properties) là cơ chế truyền dữ liệu từ component cha xuống component con. Hãy nghĩ về props như các tham số của hàm — bạn truyền vào dữ liệu, component hiển thị kết quả tương ứng.

Truyền props từ component cha

function App() {
  return (
    <div>
      {/* Truyền chuỗi */}
      <Button text="Đăng ký ngay" />

      {/* Truyền số (cần dấu {}) */}
      <Product price={299000} />

      {/* Truyền boolean — viết tắt, mặc định là true */}
      <Input disabled />

      {/* Truyền hàm */}
      <Button
        text="Xóa tài khoản"
        onClick={() => alert("Bạn có chắc không?")}
      />

      {/* Truyền object */}
      <UserCard user={{ name: "Minh", email: "minh@example.com" }} />
    </div>
  );
}

Nhận props trong Function Component

// Cách 1: Nhận toàn bộ props như một object
function Button(props) {
  return (
    <button onClick={props.onClick} disabled={props.disabled}>
      {props.text}
    </button>
  );
}

// Cách 2: Destructuring — rõ ràng và ngắn gọn hơn (khuyến nghị)
function Button({ text, onClick, disabled = false, variant = "primary" }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`btn btn-${variant}`}
    >
      {text}
    </button>
  );
}

Cách 2 (destructuring) được khuyến nghị vì bạn nhìn ngay vào danh sách tham số là biết component cần những dữ liệu gì.

Children props — Nhúng nội dung vào component

// Sử dụng component Card
function App() {
  return (
    <Card title="Khóa học React cơ bản">
      <p>Học React từ số 0, phù hợp cho người mới bắt đầu.</p>
      <a href="/courses/react-co-ban">Xem chi tiết</a>
    </Card>
  );
}

// Định nghĩa component Card
function Card({ title, children }) {
  return (
    <div className="card">
      <h3 className="card-title">{title}</h3>
      <div className="card-body">
        {children}
      </div>
    </div>
  );
}

Lưu ý quan trọng: Props là chỉ đọc (read-only). Component con tuyệt đối không được thay đổi giá trị của props:

// Sai — Không bao giờ được làm điều này
function Wrong({ name }) {
  name = "tên khác"; // Lỗi! Props không thể thay đổi
  return <p>{name}</p>;
}

Tái sử dụng và kết hợp Component

Sức mạnh thực sự của React nằm ở khả năng tái sử dụngkết hợp (composition) các component.

Thiết kế component có thể tái sử dụng

// Component Alert đa năng
function Alert({ type = "info", message }) {
  const styles = {
    success: { backgroundColor: "#d4edda", color: "#155724" },
    error:   { backgroundColor: "#f8d7da", color: "#721c24" },
    warning: { backgroundColor: "#fff3cd", color: "#856404" },
    info:    { backgroundColor: "#d1ecf1", color: "#0c5460" },
  };

  return (
    <div style={{ ...styles[type], padding: "12px 16px", borderRadius: "4px" }}>
      {message}
    </div>
  );
}

// Tái sử dụng trong nhiều tình huống khác nhau
function LoginPage() {
  return (
    <div>
      <Alert type="success" message="Đăng nhập thành công!" />
      <Alert type="error" message="Sai mật khẩu. Vui lòng thử lại." />
      <Alert type="warning" message="Tài khoản sẽ bị khóa sau 2 lần thử sai nữa." />
    </div>
  );
}

Xây dựng trang web từ các component nhỏ

// Các component riêng lẻ
function Header() {
  return (
    <header className="site-header">
      <a href="/" className="logo">VietCode</a>
      <nav>
        <a href="/articles">Bài viết</a>
        <a href="/courses">Khóa học</a>
      </nav>
    </header>
  );
}

function ArticleCard({ title, excerpt, slug }) {
  return (
    <div className="article-card">
      <h3>{title}</h3>
      <p>{excerpt}</p>
      <a href={`/articles/${slug}`}>Đọc thêm →</a>
    </div>
  );
}

function ArticleList() {
  const articles = [
    { title: "React là gì?", excerpt: "Giới thiệu về React...", slug: "react-la-gi" },
    { title: "JSX là gì?", excerpt: "Cú pháp đặc biệt của React...", slug: "jsx-la-gi" },
    { title: "Props và State", excerpt: "Quản lý dữ liệu trong React...", slug: "props-va-state" },
  ];

  return (
    <main className="article-list">
      {articles.map(article => (
        <ArticleCard
          key={article.slug}
          title={article.title}
          excerpt={article.excerpt}
          slug={article.slug}
        />
      ))}
    </main>
  );
}

function Footer() {
  return (
    <footer>
      <p>© 2026 VietCode. Tất cả quyền được bảo lưu.</p>
    </footer>
  );
}

// Ghép tất cả thành trang hoàn chỉnh
function HomePage() {
  return (
    <>
      <Header />
      <ArticleList />
      <Footer />
    </>
  );
}

Best Practices với Component trong React 2024+

Sau đây là những nguyên tắc quan trọng khi làm việc với component trong React hiện đại:

1. Luôn dùng Function Component

React Server Components (RSC), Next.js 13+ App Router, Remix — tất cả đều chỉ hỗ trợ Function Component. Nếu bạn bắt đầu học React từ hôm nay, không cần viết Class Component cho code mới.

2. Đặt tên theo PascalCase

// Đúng
function UserProfile() { return <div>...</div>; }
function ArticleCard() { return <div>...</div>; }

// Sai — React sẽ không nhận ra đây là component
function userProfile() { return <div>...</div>; }
const articlecard = () => <div>...</div>;

3. Một component, một trách nhiệm

// Không tốt — Component làm quá nhiều việc
function UserDashboard() {
  // Lấy thông tin user, đơn hàng, thông báo và hiển thị tất cả
  return <div>...rất nhiều code...</div>;
}

// Tốt hơn — Chia thành các component nhỏ
function UserDashboard() {
  return (
    <div className="dashboard">
      <UserInfo />
      <OrderList />
      <NotificationPanel />
    </div>
  );
}

4. Những lỗi phổ biến của người mới bắt đầu

// Lỗi 1: Quên đóng thẻ
// Sai
<img src="photo.jpg">
// Đúng
<img src="photo.jpg" />

// Lỗi 2: Return trên dòng mới không có dấu ngoặc
// Sai — trả về undefined
function Wrong() {
  return
    <div>Nội dung</div>;
}
// Đúng
function Correct() {
  return (
    <div>Nội dung</div>
  );
}

// Lỗi 3: Dùng class thay vì className
// Sai
<div class="container">...</div>
// Đúng
<div className="container">...</div>

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

Hỏi: Tôi mới học React, có cần học Class Component không?

Đáp: Không cần học cách viết mới. Nhưng nên biết đọc Class Component vì bạn có thể gặp trong các dự án cũ hoặc tutorial lâu đời.

Hỏi: Function Component và Class Component cái nào nhanh hơn?

Đáp: Trong thực tế, hiệu năng gần như như nhau. Lý do chọn Function Component là vì code ngắn hơn, dễ đọc hơn và được React hỗ trợ tốt hơn về lâu dài.

Hỏi: Props khác gì với State?

Đáp: Props là dữ liệu được truyền từ bên ngoài vào (component cha → component con), chỉ đọc. State là dữ liệu nội bộ của component, có thể thay đổi. Ví dụ: Props là tên sản phẩm được truyền vào thẻ sản phẩm, State là số lượng trong giỏ hàng.

Hỏi: Khi nào nên tạo component mới?

Đáp: Khi một đoạn JSX được lặp lại nhiều hơn 2–3 lần, hoặc khi một phần UI có logic riêng biệt và đủ phức tạp để tách ra.

Kết luận

Qua bài viết này, bạn đã nắm được những kiến thức nền tảng quan trọng về component trong React:

  • Component là khối UI độc lập, tái sử dụng được — là nền tảng của mọi ứng dụng React
  • JSX là cú pháp cho phép viết "HTML trong JavaScript", với một số quy tắc khác HTML thông thường
  • Function Component là cách viết được khuyến nghị hiện nay — ngắn gọn, dễ hiểu, hỗ trợ đầy đủ Hooks
  • Class Component là cách viết cũ — vẫn hoạt động nhưng không cần viết mới
  • Props là cơ chế truyền dữ liệu từ component cha xuống component con — luôn là chỉ đọc
  • Composition — kết hợp nhiều component nhỏ để xây dựng UI phức tạp

Bước tiếp theo, bạn hãy tìm hiểu về React Hooks — đặc biệt là useStateuseEffect — để thêm tính năng động vào Function Component của mình.

Về tác giả

Ảnh đại diện tác giả Kenji — họa tiết hình học

Kenji

Kỹ sư phần mềm full-stack (Web), hơn 5 năm kinh nghiệm thực tế

  • Python
  • DB
  • Hạ tầng
  • Đào tạo & cố vấn
  • AI

Làm việc cùng đồng nghiệp người Việt, tôi thấy thiếu tài liệu kỹ thuật rõ ràng bằng tiếng Việt. codeahoc là nơi tôi chia sẻ theo hướng thực tế, dễ áp dụng.

Nguyên tắc nội dung

  • Ưu tiên nguồn gốc và góc nhìn từ thực tế triển khai.
  • Nếu có sai sót, nội dung sẽ được cập nhật và sửa kịp thời.

Khóa học liên quan

React - The Complete Guide (incl. React Router & Redux)

Làm chủ React.js với hooks, Redux và dự án thực tế.

4.6499.000 ₫
Xem khóa học →

The Complete Web Developer Bootcamp

HTML, CSS, JavaScript và nền tảng trước khi đi sâu React.

4.7499.000 ₫
Xem khóa học →
Quảng cáo