Skip to main content

Що таке HOC?

Коротке визначення

Higher-Order Component (HOC) - це функція, яка приймає компонент як аргумент і повертає новий компонент, додаючи йому додаткову поведінку або дані.

Тобто:

HOC = функція, що обгортає компонент, щоб "розширити" його функціональність.


Приклад в один рядок

javascript
const EnhancedComponent = withSomething(BaseComponent);

Тут:

  • BaseComponent - твій звичайний компонент;
  • withSomething - функція HOC;
  • EnhancedComponent - новий компонент з доданою логікою.

Приклад 1. Найпростіший HOC - логування рендеру

javascript
function withLogger(WrappedComponent) { return function Enhanced(props) { console.log(`Рендериться компонент: ${WrappedComponent.name}`); return <WrappedComponent {...props} />; }; }

Використання:

javascript
function Hello({ name }) { return <h1>Hello, {name}</h1>; } const HelloWithLogger = withLogger(Hello); // ... <HelloWithLogger name="Alex" />;

Що відбувається:

  • withLogger повертає новий компонент;
  • при кожному рендері в консоль виводиться ім'я компонента;
  • оригінальний компонент (Hello) отримує всі props без змін.

Приклад 2. HOC, що додає дані

javascript
function withUser(WrappedComponent) { return function Enhanced(props) { const user = { name: "Alex", role: "admin" }; return <WrappedComponent {...props} user={user} />; }; } function Profile({ user }) { return <p>Користувач: {user.name}</p>; } const ProfileWithUser = withUser(Profile);

Тепер ProfileWithUser - це версія Profile, яка завжди отримує user через props, без потреби дублювати цю логіку в кожному компоненті.


Приклад 3. Додавання стану або ефектів

javascript
function withWindowWidth(WrappedComponent) { return function Enhanced(props) { const [width, setWidth] = useState(window.innerWidth); useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []); return <WrappedComponent {...props} width={width} />; }; } function Info({ width }) { return <p>Ширина вікна: {width}px</p>; } const InfoWithWidth = withWindowWidth(Info);

Тепер InfoWithWidth автоматично отримує поточну ширину вікна, і компоненту Info не потрібно знати, як це обчислюється.


Важливі принципи HOC

  1. Не змінюй вихідний компонент HOC має обгортати, а не мутувати компонент. Погано:
javascript
WrappedComponent.prototype.newMethod = () => {}

Добре:

javascript
return function Enhanced() { return <WrappedComponent />; };
  1. Передавай props далі Завжди прокидуй ...props, щоб не втрачати передані властивості:
javascript
return <WrappedComponent {...props} />;
  1. Зберігай читабельне ім'я компонента У HOC часто роблять:
javascript
Enhanced.displayName = `withLogger(${WrappedComponent.displayName || WrappedComponent.name})`;
  1. Не зловживай вкладеністю Багато HOC поспіль створюють "піраміду":
javascript
withTheme(withAuth(withRouter(withLogger(App))))

Це погіршує читабельність і дебаг.


Приклад 4. Реальний кейс - HOC в Redux

Найвідоміший HOC - connect() з React Redux:

javascript
import { connect } from "react-redux"; function Profile({ user }) { return <p>Hello, {user.name}</p>; } const mapState = (state) => ({ user: state.user }); export default connect(mapState)(Profile);

Тут connect:

  • підписує компонент на Redux-store;
  • передає стан у вигляді props;
  • повертає новий компонент, що обгортає Profile.

Коли використовувати HOC

Коли потрібно повторно використати логіку між компонентами:

  • авторизація / доступ (withAuth)
  • обробка помилок (withErrorBoundary)
  • завантаження даних (withDataFetch)
  • вимірювання розміру вікна, позиції миші тощо

Не варто використовувати:

  • якщо те саме можна виразити через хуки (useUser, useWindowWidth тощо);
  • коли виникає "драбинка" вкладених компонентів.

Сучасна альтернатива: Хуки

Після появи хуків (React 16.8) HOC майже завжди замінюються хуками:

javascript
// Замість HOC const ProfileWithUser = withUser(Profile); // Можна просто: function Profile() { const user = useUser(); return <p>{user.name}</p>; }

Хуки простіші, читабельніші і не створюють вкладених структур.


Підсумок

ЩоОпис
HOCФункція, яка приймає компонент і повертає новий
МетаДодати компоненту спільну логіку або дані
ПрикладwithLogger(Component), connect(mapState)(Component)
Не робитьЗмін всередині вихідного компонента
Сучасна альтернативаКастомні хуки (useAuth, useTheme, useUser)

Головна думка:

Higher-Order Component - це "обгортка", яка розширює можливості компонента, не змінюючи його вихідний код. Сьогодні HOC дедалі частіше замінюють хуками, але принцип "обгортання" лишився фундаментальним для React.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.