Functional Component trong React — Tiêu chuẩn phát triển hiện đại

Tác giả: IT Sectr Đã đăng: 2026-07-04 Thời gian đọc: 9 phút

Functional Component — là cách tạo component React bằng các hàm JavaScript thông thường, đã trở thành tiêu chuẩn sau khi React 16.8 ra mắt và hooks xuất hiện. Functional component nhận props và trả về các phần tử React mà không yêu cầu kế thừa từ React.Component. Theo React, 2024, 97% component mới trong hệ sinh thái React được viết dưới dạng hàm.

Những Điểm Chính

  • Functional Component — một hàm JavaScript thông thường nhận props và trả về JSX, không cần extends Component.
  • Hooks (useState, useEffect, useContext) cung cấp cho functional component quyền truy cập đầy đủ vào state và vòng đời.
  • Tính dễ đọc — functional component ngắn hơn class component, không cần constructor, bind và các phương thức vòng đời thừa.
  • Hiệu suất — React tối ưu hóa functional component thông qua memoization và khởi tạo lười biếng.
  • Khuyến nghị React — tất cả các dự án mới chỉ nên sử dụng functional component với hooks.

Functional Component là gì?

Functional Component là một component React được định nghĩa như một hàm nhận đối tượng props và trả về một phần tử React. Trước React 16.8, các component này được gọi là stateless vì chúng không thể quản lý trạng thái nội bộ.

Với sự ra đời của hooks trong React 16.8 (tháng 2 năm 2019), functional component đã có quyền truy cập vào state (useState), hiệu ứng phụ (useEffect), ngữ cảnh (useContext) và ref (useRef). Thuật ngữ “stateless” đã lỗi thời — functional component hiện đại quản lý state một cách đầy đủ.

React chính thức khuyến nghị functional component là cách chính để tạo component. Tất cả tài liệu trên react.dev, ví dụ, hướng dẫn và API mới (Server Components, Actions) đều được xây dựng trên phương pháp hàm. Class component không bị loại bỏ, nhưng các tính năng mới của React chỉ khả dụng thông qua hooks.

Tạo Functional Component

Functional component đơn giản nhất là một hàm trả về JSX. Nó nhận props làm đối số, không yêu cầu constructor, gọi super hay ràng buộc this. Props có thể truy cập trực tiếp qua đối số của hàm — không cần this.props.

js
// Functional component without state
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Arrow function (common variant)
const Greeting = ({ name }) => (
  <h1>Hello, {name}!</h1>
);

Component với State

Để thêm state, sử dụng useState. Hook trả về một tuple gồm hai giá trị: state hiện tại và hàm setter. Không giống this.setState dựa trên class, useState thay thế hoàn toàn giá trị thay vì hợp nhất với giá trị trước đó.

js
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Hooks trong Functional Component

Hooks là nền tảng của React hiện đại. Mỗi hook giải quyết một nhiệm vụ cụ thể: useState — state, useEffect — hiệu ứng phụ, useContext — truy cập ngữ cảnh, useRef — tham chiếu phần tử DOM, useCallbackuseMemo — memoization.

useEffect cho Hiệu ứng Phụ

useEffect thay thế đồng thời componentDidMount, componentDidUpdate và componentWillUnmount. Đối số đầu tiên là callback với hiệu ứng, đối số thứ hai là mảng phụ thuộc. Nếu mảng trống, hiệu ứng chạy một lần sau khi gắn kết. Nếu phụ thuộc được chỉ định, nó chạy khi bất kỳ phụ thuộc nào thay đổi.

js
import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    let cancelled = false;

    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        if (!cancelled) setUser(data);
      });

    // Cleanup - analog of componentWillUnmount
    return () => { cancelled = true; };
  }, [userId]); // Dependency

  return <div>{user?.name}</div>;
}

Custom Hooks

Ưu điểm chính của functional component là tái sử dụng logic thông qua custom hooks. Trong khi ở class component, logic bị trùng lặp giữa componentDidMount và componentDidUpdate, thì trong functional component, nó được trích xuất thành một hàm riêng với tiền tố use. Custom hooks là giải pháp thay thế chính cho HOC và render props.

Kết hợp thay vì Kế thừa

React khuyến nghị kết hợp thay vì kế thừa để tái sử dụng code giữa các component. Functional component lý tưởng cho việc kết hợp: một component có thể chứa nhiều component khác, truyền props và children cho chúng.

Mẫu children — khi một component nhận các phần tử con qua prop children — được triển khai tự nhiên: function Layout({ children }). Tương tự slots của Vue được triển khai qua props component có tên: function Page({ header, sidebar, content }).

Kế thừa hiếm khi được sử dụng trong React. Ngay cả class component, về mặt kỹ thuật hỗ trợ extends, hiếm khi tạo thành hệ thống phân cấp sâu hơn một cấp. Functional component với kết hợp hoàn toàn đáp ứng nhu cầu tái sử dụng code mà không cần kế thừa.

Tối ưu Hiệu suất

Functional component đi kèm với cơ chế tối ưu hóa tích hợp. React.memo — tương đương PureComponent cho hàm: ngăn chặn việc kết xuất lại nếu props không thay đổi (so sánh nông). useMemo lưu trữ kết quả tính toán giữa các lần kết xuất.

js
import React, { useMemo } from 'react';

// React.memo - memoize component
const ExpensiveList = React.memo(({ items }) => {
  return <ul>
    {items.map(item =>
      <li key={item.id}>{item.name}</li>
    )}
  </ul>;
});

// useMemo - caching result
function Dashboard({ transactions }) {
  const summary = useMemo(() => {
    return transactions.reduce((acc, t) => acc + t.amount, 0);
  }, [transactions]);

  return <p>Total: {summary}</p>;
}

useCallback ghi nhớ các hàm callback để chúng không bị tạo lại mỗi lần kết xuất. Điều này rất quan trọng khi truyền hàm cho component con được bọc trong React.memo: nếu không có useCallback, component con sẽ kết xuất lại mỗi lần vì tham chiếu hàm thay đổi.

Functional vs Class Component

Sự khác biệt giữa các phương pháp vượt ra ngoài cú pháp. Functional component là closure: state và hiệu ứng được gắn với một lần kết xuất cụ thể. Class component sử dụng this: state luôn được lấy từ this.state, có thể đã lỗi thời khi callback bất đồng bộ thực thi.

Khía cạnhFunctionalClass
StateuseState (riêng biệt)this.state + this.setState
Hiệu ứnguseEffect với phụ thuộccomponentDidMount + componentDidUpdate
Ngữ cảnhuseContextContext.Consumer hoặc static contextType
Tối ưu hóaReact.memo + useMemoPureComponent + shouldComponentUpdate
Tái sử dụng logicCustom hooksHOC / Render props
thisKhông cóbind trong constructor

Functional component cung cấp luồng thực thi tuyến tính. Trong class component, logic liên quan thường bị phân tán trên nhiều phương thức vòng đời. Ví dụ, đăng ký WebSocket được thiết lập trong componentDidMount và hủy bỏ trong componentWillUnmount. Trong functional component, cả hai thao tác đều nằm trong một useEffect duy nhất với hàm dọn dẹp trả về.

TypeScript và Functional Component

TypeScript hoạt động tự nhiên hơn với functional component so với class. Định kiểu props — một interface cho đối số hàm. Kiểu trả về là JSX.Element hoặc ReactNode. useState tự động suy luận kiểu từ giá trị khởi tạo.

ts
import React, { useState } from 'react';

interface ButtonProps {
  label: string;
  variant?: 'primary' | 'secondary';
  onClick: () => void;
}

const Button: React.FC<ButtonProps> =
  ({ label, variant = 'primary', onClick }) => (
    <button
      className={`btn btn-${variant}`}
      onClick={onClick}
    >
      {label}
    </button>
  );

TypeScript hiện đại cho phép định kiểu useReducer với kiểu union phân biệt, Generics trong custom hooks và xác thực children nghiêm ngặt qua React.PropsWithChildren. Functional component với TypeScript cung cấp an toàn kiểu đầy đủ mà không cần trừu tượng bổ sung.

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

Tại sao React khuyến nghị functional component?

Functional component đơn giản hơn: không có constructor, bind, this hay các phương thức vòng đời phân tán. Hooks cho phép nhóm logic liên quan. React đầu tư nguồn lực vào phát triển hooks, không phải class. Server Components và các tính năng mới chỉ khả dụng trong hàm.

Tôi có thể sử dụng setInterval trong functional component không?

Có, thông qua useEffect với bộ đếm thời gian bên trong và hàm dọn dẹp cho clearInterval. Hãy chú ý đến closure: nếu bạn đang tăng bộ đếm, hãy sử dụng dạng hàm của setState: setCount(c => c + 1) để không phụ thuộc vào giá trị cũ trong closure.

Làm thế nào để lấy props trước đó trong functional component?

Sử dụng useRef để lưu trữ giá trị trước đó. Cập nhật ref trong useEffect sau mỗi lần kết xuất. Custom hook usePrevious giúp so sánh sạch sẽ: const prev = usePrevious(value);

React.memo khác useMemo như thế nào?

React.memo là HOC để ghi nhớ toàn bộ component: ngăn kết xuất lại nếu props không thay đổi. useMemo là hook để ghi nhớ một giá trị cụ thể bên trong component: lưu trữ kết quả hàm giữa các lần kết xuất theo mảng phụ thuộc.

Làm thế nào để mô phỏng getDerivedStateFromProps trong functional component?

Cách đơn giản nhất là useState với khởi tạo từ props + useEffect với phụ thuộc vào props để đồng bộ hóa. Cho các trường hợp hiếm, React khuyến nghị sử dụng key để buộc tạo lại component khi dữ liệu đầu vào thay đổi.

Tổng kết

  • Functional Component — tiêu chuẩn React hiện đại: một hàm nhận props và trả về JSX.
  • Hooks (useState, useEffect) cung cấp cho functional component state, hiệu ứng và ngữ cảnh mà không cần class.
  • Kết hợp thông qua children và custom hooks thay thế kế thừa và các mẫu HOC.
  • React.memo và useMemo cung cấp tối ưu hóa hiệu suất cho functional component.
  • TypeScript với functional component cung cấp định kiểu props nghiêm ngặt và suy luận kiểu tự động.
  • useEffect thay thế tất cả phương thức vòng đời của class component tại một nơi.
  • Custom hooks cho phép trích xuất và tái sử dụng logic giữa các component mà không cần HOC.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm