<aside> 💡 Higher Order Component (HOC) là một mẫu thiết kế trong React được sử dụng để tái sử dụng logic của các component. HOC không phải là một phần của API React, mà là một kỹ thuật xuất phát từ bản chất compositional của React.
</aside>
Định nghĩa và Cách Hoạt Động
Một Higher Order Component là một hàm nhận vào một component và trả về một component mới với một số tính năng hoặc logic bổ sung. Cụ thể, HOC là một hàm có cú pháp như sau:
const EnhancedComponent = higherOrderComponent(WrappedComponent);
Ví dụ Minh Họa
Giả sử bạn có một component hiển thị thông tin người dùng, và bạn muốn thêm khả năng kiểm tra quyền truy cập (authorization) vào component này. Bạn có thể tạo một HOC để thêm logic kiểm tra quyền truy cập.
import React from 'react';
// Higher Order Component
const withAuthorization = (WrappedComponent) => {
return (props) => {
if (!props.isAuthorized) {
return <div>Access Denied</div>;
}
return <WrappedComponent {...props} />;
};
};
Sau đó, bạn có thể sử dụng HOC này để “bọc” component của bạn:
// Component hiển thị thông tin người dùng
const UserComponent = (props) => {
return <div>Welcome, {props.userName}!</div>;
};
// Sử dụng HOC để bọc UserComponent
const AuthorizedUserComponent = withAuthorization(UserComponent);
// Sử dụng AuthorizedUserComponent trong ứng dụng của bạn
const App = () => {
return (
<div>
<AuthorizedUserComponent isAuthorized={true} userName="John Doe" />
<AuthorizedUserComponent isAuthorized={false} userName="Jane Doe" />
</div>
);
};
export default App;
Coding Conventions
Đặt tên HOC đúng cách
- Sử dụng tiền tố
withđể dễ nhận biết rằng đây là một HOC. Ví dụ:withAuthorization,withLogging
Sử dụng cú pháp hàm
HOCsnên được viết dưới dạng hàm, nhận vào mộtcomponentvà trả về mộtcomponentmới
const withHOC = (WrappedComponent) => {
return (props) => {
// Logic của HOC
return <WrappedComponent {...props} />;
};
};
Truyền props đúng cách
Đảm bảo rằng HOC truyền tất cả các props xuống component được bọc
return <WrappedComponent {...props} />;
Best Practices
Tránh gây thay đổi nguyên bản (mutate) props
HOCskhông nên thay đổi cácpropsmà chúng nhận được. Nếu cần thiết, hãy tạo các props mới thay vì thay đổi các props hiện tại.
Không sử dụng HOCs trong hàm render
- Tránh sử dụng HOCs bên trong hàm
rendercủa component để tránh việc tạo ra component mới mỗi khi render
// Không nên làm như thế này
const Component = () => {
const EnhancedComponent = withHOC(MyComponent);
return <EnhancedComponent />;
};
Hiệu suất
- Sử dụng
React.memocho các component được bọc nếu cần thiết để tối ưu hóa hiệu suất
const WrappedComponent = React.memo((props) => {
// Component logic
});
Ref không nên được truyền qua props
Hiển thị tên component cho mục đích debug
const getDisplayName = (WrappedComponent) => {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
};
const withHOC = (WrappedComponent) => {
const EnhancedComponent = (props) => {
// Logic của HOC
return <WrappedComponent {...props} />;
};
EnhancedComponent.displayName = `withHOC(${getDisplayName(WrappedComponent)})`;
return EnhancedComponent;
};
Tên của HOC có thể xem được thông qua React Developer Tool, mặc định tên của HOC là Anonymous
Các build in React HOCs phổ biến
Trong React
memolazy
Ngoài React
connect–react-reduxwithRouter–react-router-domwithStyles–Material-UIwithApollo–react-apollowithTranslation–react-i18nextwithTheme–styled-componentswithFormik–formik
