Skip to main content

Що робить "Higher-Order Component (HOC)"?

Визначення

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

Можна сказати:

HOC - це «компонент-над-компонентом» (аналог декоратора чи обгортки, що додає поведінку).


Формула HOC

javascript
const EnhancedComponent = withSomething(BaseComponent);

де withSomething - це HOC-функція, а BaseComponent - вихідний компонент, якому додається логіка.


Приклад: додамо дані про користувача через HOC

1. Вихідний компонент

javascript
function UserProfile({ user }) { return <p>Привіт, {user.name}!</p>; }

2. HOC, який передає дані в props

javascript
function withUser(WrappedComponent) { return function EnhancedComponent(props) { const user = { name: 'Tim', age: 25 }; // імітація даних return <WrappedComponent {...props} user={user} />; }; }

3. Використовуємо

javascript
const UserProfileWithUser = withUser(UserProfile); export default function App() { return <UserProfileWithUser />; }

Тепер UserProfile нічого не знає про те, звідки береться user - HOC додав цю поведінку "ззовні".


Що робить HOC по суті

HOC:

  • не змінює вихідний компонент,
  • не успадковується від нього,
  • а створює новий компонент, який композує старий + нову логіку.

Реальний приклад: connect() з Redux

javascript
import { connect } from "react-redux"; function MyComponent({ user }) { return <div>{user.name}</div>; } export default connect( (state) => ({ user: state.user }) )(MyComponent);

Тут connect() - це класичний HOC, який зв'язує компонент зі стором Redux і прокидає потрібні дані в props.


Приклад додавання поведінки: логування

javascript
function withLogger(WrappedComponent) { return function (props) { console.log(`Рендериться компонент: ${WrappedComponent.name}`); return <WrappedComponent {...props} />; }; } function Hello({ name }) { return <h1>Привіт, {name}!</h1>; } const HelloWithLogger = withLogger(Hello);

Тепер при кожному рендері буде логуватися ім'я компонента.


Правила написання HOC

  1. HOC - це функція, яка повертає компонент:
javascript
const withSomething = (Component) => (props) => <Component {...props} />;
  1. Не змінюй вихідний компонент! -> Створюй новий, обгортаючи старий.
  2. Передавай усі пропси далі, щоб не "розірвати" ланцюжок:
javascript
return <WrappedComponent {...props} extra={data} />;
  1. Зберігай ім'я для зручності відлагодження:
javascript
Enhanced.displayName = `withSomething(${WrappedComponent.displayName || WrappedComponent.name})`;

Що вирішує HOC

ПроблемаЯк вирішує HOC
Повторювана логіка в різних компонентахОбгортає їх спільною поведінкою
Підключення до зовнішніх данихДодає потрібні props (наприклад, з Redux чи контексту)
Робота з авторизацією / ролямиПеревіряє доступ і вирішує, чи рендерити компонент
Логування, аналітика, обробка помилокДодає поведінку при рендері

Мінуси HOC

ПроблемаОпис
Вкладеність обгортокДекілька HOC створюють "шаруватий пиріг" (withAuth(withRouter(withTheme(...))))
Важко відстежувати пропсиHOC може непомітно додавати або перевизначати props
Неочевидні залежностіЛогіка схована в обгортці
Хуки витіснили HOCУ сучасному React майже все вирішується хуками (useUser(), useAuth())

Сучасна альтернатива - хуки

Патерн HOC був головним способом переюзання логіки до появи хуків. Тепер те саме робиться простіше:

Було (HOC)

javascript
const withUser = (Component) => (props) => { const user = useUser(); return <Component {...props} user={user} />; };

Стало (Hook)

javascript
function Profile() { const user = useUser(); return <p>{user.name}</p>; }

Хуки дають той самий ефект - "вбудовування логіки" - але без обгортання компонентів.


Підсумок

ЩоОпис
ВизначенняФункція, яка приймає компонент і повертає новий
ЦільПереюзання логіки без дублювання
ПринципКомпонент + обгортка = новий компонент
Прикладconnect() з Redux, withRouter() з React Router
АльтернативаКастомні хуки
Аналогія"Декоратор", що додає можливості

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

HOC - це спосіб "надбудувати" поведінку над компонентом, не чіпаючи його вихідний код. Він був попередником сучасних хуків, і досі використовується, коли потрібна обгортка "на рівні компонента", а не "всередині нього".

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

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

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