---
title: "So sánh giữa HOCs, Render Props và Hooks."
description: "So sánh ba phương pháp tái sử dụng logic giữa các component: Higher-Order Components (HOCs), Render Props, và Hooks"
canonical: "https://200lab.io/blog/so-sanh-hocs-vs-render-props-vs-hooks"
published: "2024-12-05T04:12:58Z"
updated: "2026-08-21T07:17:48Z"
authors: ["Tran Thuy Vy"]
tags: ["Frontend"]
reading_minutes: 8
access: "public"
---

Chủ đề hôm nay mình muốn chia sẻ với các bạn về ba pattern phổ biến trong React: Higher-Order Components (HOCs), Render Props, và Hooks. Đây đều là những công cụ giúp bạn tái sử dụng logic giữa các component. Hãy cùng tìm hiểu từng phương pháp, so sánh chúng, và xem xét khi nào nên sử dụng phương pháp nào. Mình cũng sẽ cung cấp các ví dụ và đoạn code cụ thể để minh họa sự khác nhau giữa chúng.

## 1. So sánh tổng quan

      Higher-Order Components (HOCs)
      Render Props
      Hooks

      **Cơ chế triển khai**
      Hàm nhận component và trả về component mới
      Component nhận prop là một hàm render
      Sử dụng trong functional components với hooks

      **Tái sử dụng logic**
      Bằng cách bọc component
      Bằng cách sử dụng hàm render
      Bằng cách tạo custom hooks

      **Độ phức tạp code**
      Có thể cao khi lồng nhiều HOC
      Có thể gây lồng nhau trong JSX
      Thường ngắn gọn và dễ đọc

      **Xung đột tên**
      Có thể xảy ra, cần cẩn thận
      Tránh được xung đột tên
      Tránh được xung đột tên

      **Khả năng debug**
      Khó hơn do nhiều lớp bọc
      Trung bình, có thể khó với nhiều render props
      Dễ hơn, stack trace rõ ràng

      **Hỗ trợ**
      Hoạt động với cả class và functional components
      Hoạt động với cả class và functional components
      Chỉ hoạt động với functional components

      **Hiệu suất**
      Có thể ảnh hưởng nếu không tối ưu
      Có thể ảnh hưởng do tạo hàm mới mỗi lần render
      Tối ưu hơn, hooks được React tối ưu

      **Độ phổ biến hiện tại**
      Ít phổ biến hơn do sự xuất hiện của hooks
      Vẫn được sử dụng trong một số trường hợp
      Rất phổ biến và được khuyến nghị

## 2. Cơ chế hoạt động

Trong phần này, mình sẽ mô tả cơ chế hoạt động của từng phương pháp, kèm theo mô tả về sơ đồ minh họa để giúp bạn hình dung rõ hơn.

### 2.1 HOCs

HOC là hàm nhận vào component và trả về một component mới, cho phép bạn thêm hoặc thay đổi hành vi của component gốc mà không cần sửa đổi nó.

![Cơ chế hoạt động của HOC](https://assets.200lab.io/images/2024/12/05/co-che-hoat-dong-hoc-2a5893cd26c0325c4b19.webp)

- Original Component (ComponentA): component gốc mà bạn muốn mở rộng hoặc thêm logic mới.
- HOC Function (withExtraLogic): HOC nhận vào ComponentA làm tham số.
- Enhanced Component (ComponentB): kết quả của HOC sau khi áp dụng logic bổ sung lên ComponentA.
- Rendered Output: giao diện được render ra sau khi sử dụng ComponentB.

### 2.2 Render props

Sử dụng prop có giá trị là hàm để kiểm soát những gì được render.

![Cơ chế hoạt động render props](https://assets.200lab.io/images/2024/12/05/co-che-hoat-dong-render-props-41abbf2b976c084a56fb.webp)

- Component cha (DataProvider): chứa logic chung và gọi hàm render prop.
- Hàm render prop (children): hàm được truyền vào `DataProvider` để quyết định render gì dựa trên dữ liệu nhận được.
- Component con (ChildComponent): được render thông qua hàm render prop, sử dụng dữ liệu từ `DataProvider`.

### 2.3 Hook

Sử dụng các hàm hook để thêm state và các tính năng React khác vào functional components.

![Cơ chế hoạt động Hook](https://assets.200lab.io/images/2024/12/05/co-che-hoat-dong-hook-dabce1f00ec5b64e8f65.webp)

- Functional Component (MyComponent): Dùng hooks để quản lý state và side effects.
- Custom Hook (useCustomLogic): chứa logic chung, có thể được tái sử dụng.
- State và Side Effects: được quản lý trong MyComponent thông qua hooks.

## 3. Ví dụ và code

Mình sẽ lấy ví dụ: get data từ API và hiển thị trong component.

### 3.1 Triển khai với HOCs (Higher-Order Components)

```
import React from 'react';

function withDataFetching(WrappedComponent, dataSource) {
  return class extends React.Component {
    state = {
      data: [],
      isLoading: false,
      error: null,
    };

    componentDidMount() {
      this.setState({ isLoading: true });
      fetch(dataSource)
        .then(response => response.json())
        .then(data => this.setState({ data, isLoading: false }))
        .catch(error => this.setState({ error, isLoading: false }));
    }

    render() {
      return (
        <WrappedComponent
          {...this.props}
          data={this.state.data}
          isLoading={this.state.isLoading}
          error={this.state.error}
        />
      );
    }
  };
}

export default withDataFetching;
```

- Sử dụng trong `UserList.js`

```
import React from 'react';
import withDataFetching from './withDataFetching';

function UserList({ data, isLoading, error }) {
  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error fetching data!</p>;
  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default withDataFetching(UserList, 'https://api.example.com/users');
```

`withDataFetching` bọc `UserList`, thêm logic lấy dữ liệu và truyền dữ liệu thông qua `props`.

Bạn có thể thấy được những điểm hạn chế khi sử dụng HOCs:

- Có thể xảy ra xung đột tên với các props khác.
- Code có thể khó debug khi bạn lồng nhiều HOC.
- Không linh hoạt trong việc kiểm soát render.

### 3.2 Triển khai với Render Props

```
import React from 'react';

class DataFetcher extends React.Component {
  state = {
    data: [],
    isLoading: false,
    error: null,
  };

  componentDidMount() {
    const { url } = this.props;
    this.setState({ isLoading: true });
    fetch(url)
      .then(response => response.json())
      .then(data => this.setState({ data, isLoading: false }))
      .catch(error => this.setState({ error, isLoading: false }));
  }

  render() {
    return this.props.children({
      data: this.state.data,
      isLoading: this.state.isLoading,
      error: this.state.error,
    });
  }
}

export default DataFetcher;
```

- Sử dụng Render Props trong `UserList.js`

```
import React from 'react';
import DataFetcher from './DataFetcher';

function UserList() {
  return (
    <DataFetcher url="https://api.example.com/users">
      {({ data, isLoading, error }) => {
        if (isLoading) return <p>Loading...</p>;
        if (error) return <p>Error fetching data!</p>;
        return (
          <ul>
            {data.map(user => (
              <li key={user.id}>{user.name}</li>
            ))}
          </ul>
        );
      }}
    </DataFetcher>
  );
}

export default UserList;
```

- `DataFetcher` chứa logic để lấy dữ liệu và gọi hàm render prop với dữ liệu đó.
- `UserList` sử dụng render prop để quyết định render gì dựa trên dữ liệu nhận được.

Những điểm hạn chế khi sử dụng:

- Sử dụng sẽ dẫn đến việc lồng nhau trong JSX, làm code trở nên khó đọc.
- Mỗi lần render tạo ra một function mới, có thể ảnh hưởng đến hiệu suất.

### 3.3 Triển khai với Hooks

```
import { useState, useEffect } from 'react';

function useDataFetching(dataSource) {
  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    setIsLoading(true);
    fetch(dataSource)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setIsLoading(false);
      })
      .catch(error => {
        setError(error);
        setIsLoading(false);
      });
  }, [dataSource]);

  return { data, isLoading, error };
}

export default useDataFetching;
```

- Sử dụng Hooks trong `UserList.js`

```
import React from 'react';
import useDataFetching from './useDataFetching';

function UserList() {
  const { data, isLoading, error } = useDataFetching('https://api.example.com/users');

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error fetching data!</p>;
  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
```

- `useDataFetching` là custom hook chứa logic để lấy dữ liệu.
- `UserList` gọi hook này và nhận về dữ liệu, sau đó render trực tiếp.

Những điểm hạn chế của hooks:

- Không thể sử dụng hooks trong class components.
- Phải tuân theo các quy tắc như không gọi hooks trong vòng lặp, điều kiện, hoặc hàm lồng nhau.

Từ những phần trên mình có thể đưa ra kết luận như thế này:

1. Hooks giải quyết hạn chế:

- Tránh xung đột tên: hooks không cần bọc component hoặc truyền props
- Code ngắn gọn hơn: không có lồng nhau trong JSX như Render Props.
- Dễ debug hơn: không có nhiều lớp bọc như HOCs.

1. Render Props giải quyết hạn chế:

- Tránh xung đột tên: do không truyền thêm props vào component con.
- Kiểm soát linh hoạt cách render: Component con quyết định render gì dựa trên dữ liệu nhận được.

1. HOCs giải quyết hạn chế:

- Tránh lồng nhau trong JSX: HOCs không làm tăng mức độ lồng nhau như Render Props.
- Có thể sử dụng với class components: HOCs hoạt động với cả class và functional components, trong khi Hooks chỉ hoạt động với functional components.

## 4. Khi nào nên sử dụng phương pháp nào?

### 4.1 Sử dụng Hooks khi

- Bạn đang sử dụng React phiên bản 16.8 trở lên.
- Bạn làm việc với functional components.
- Bạn muốn code ngắn gọn, dễ đọc và dễ bảo trì.
- Bạn muốn tránh xung đột tên và lồng nhau trong JSX.

### 4.2 Sử dụng Render Props khi

- Bạn cần kiểm soát linh hoạt cách render của component con.
- Bạn làm việc với class components hoặc cần tương thích với code cũ.
- Bạn muốn tránh xung đột tên mà HOCs có thể gây ra.

### 4.4 Sử dụng HOCs khi

- Bạn làm việc với class components và không thể sử dụng Hooks.
- Bạn cần tái sử dụng logic chung mà không muốn thay đổi cấu trúc component hiện có.
- Bạn muốn tránh lồng nhau trong JSX mà Render Props có thể gây ra.

## 5. Kết luận

Trong React, việc lựa chọn giữa Higher-Order Components, Render Props, và Hooks phụ thuộc vào hoàn cảnh cụ thể của dự án và nhu cầu của bạn. Mỗi phương pháp đều có ưu điểm và hạn chế riêng.

Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về sự khác nhau giữa HOCs, Render Props và Hooks, cũng như cách áp dụng chúng trong dự án của mình.

Các bài viết liên quan:

- [Render Props pattern là gì? Hướng dẫn sử dụng Render Props](</blog/render-props-pattern-la-gi>)
- [HOCs Pattern là gì? Hướng dẫn triển khai Hocs Pattern trong dự án React](</blog/hoc-pattern-la-gi>)
- [Hooks Pattern là gì? Hướng dẫn áp dụng Hooks Pattern trong dự án React](</blog/hooks-pattern-la-gi-huong-dan-ap-dung-hooks-pattern-trong-du-an-react-2>)
- [React Toastify là gì? Hướng dẫn sử dụng Toast Notification với React Toastify](</blog/react-toastify-la-gi>)
