Khái niệm higher order component (HOC) cũng giống như higher order function (xem thêm xem thêm Callback). Chỉ có một vài sự khác biệt nhỏ:

  • Higher order function hoặc là nhận hàm vào làm đối số, hoặc là dùng hàm làm giá trị trả về, chỉ cần một trong hai.
  • Higher order component cần cả hai điều kiện: phải nhận component vào đối số giá trị trả về cần phải là một component. Phần lớn các thư viện đều sử dụng HOC, chẳng hạn như Redux, React Router hay là Material UI.

Ví dụ:

function HigherOrderComponent(Component) {
  return (props) => {
    return <Component {...props} />
  }
}

Component Factory

Có thể dùng HOC để triển khai component factory.

Ví dụ: tạo ra một component factory cho phép sản xuất ra nhiều loại button component có các theme khác nhau dựa trên các tham số truyền vào.

Giả sử ta có các theme sau:

const themes = [
  { name: "light", color: "#000", backgroundColor: "#fff" },
  { name: "dark", color: "#fff", backgroundColor: "#000" },
]

Đầu tiên, ta tạo ra một button component làm component gốc:

function Button({ style, text, onClick }) {
  return (
    <button style={style} onClick={onClick}>
      {text}
    </button>
  )
}

Sau đó, ta tạo ra một component đóng vai trò sản xuất các button component: ButtonFactory. Component này sẽ nhận vào hai tham số:

  • Tham số thứ nhất là tên của button component.
  • Tham số thứ hai là tên phân loại của button. Tham số này giúp cho ButtonFactory tạo ra button component dựa trên theme của phân loại đó.
function ButtonFactory(themeName = "light") {
  const { name, color, backgroundColor } = themes.find((theme) => theme.name === themeName)
 
  const style = { color, backgroundColor }
  const text = `${name} button`
 
  const ResultComponent = (props) => {
    return <Button style={style} text={text} {...props} />
  }
 
  return ResultComponent
}

Kế đến, tạo ra các button component:

const LightButton = ButtonFactory()
const DarkButton = ButtonFactory("dark")

Cuối cùng, ta gọi sử dụng các button component như sau:

function App() {
  return (
    <div>
      <LightButton onClick={() => console.log("Light Button is clicked")} />
      <DarkButton onClick={() => console.log("Dark Button is clicked")} />
    </div>
  )
}

Có thể thấy, ButtonFactory có cách hoạt động tương tự như design pattern Factory Method.

Higher order component giúp chúng ta có thể tái sử dụng component và nâng cấp component với các event handlers và styles được truyền vào từ tham số.

Resources