Что такое higher-order-components?
Паттерны и подходы
Higher-Order Component (HOC) — функция, принимающая компонент и возвращающая новый компонент с дополнительным поведением. Паттерн переиспользования логики из «дохуковой» эпохи.
Форма
const withLoading = (Component) => {
return function WithLoading({ isLoading, ...rest }) {
if (isLoading) return <Spinner />;
return <Component {...rest} />;
};
};
const UserList = withLoading(UserListInner);HOC не изменяет исходный компонент — оборачивает его: добавляет props, подписки, условный рендеринг.
Известные примеры
connect(mapState, mapDispatch) (react-redux), withRouter (старый React Router), withTranslation (i18next) и даже React.memo — формально тоже HOC.
Правила
- Пробрасывать props (
{...rest}) и ref (через forwardRef). - Задавать displayName (
withLoading(UserList)) для отладки. - Не создавать HOC внутри рендера: каждый вызов даёт новый тип компонента — React будет пересоздавать поддерево.
- Не мутировать исходный компонент.
Почему уступили хукам
Композиция HOC читается плохо (withA(withB(withC(Page)))), в DevTools — «матрёшка» обёрток, имена props конфликтуют, источник пропа неочевиден. Кастомные хуки решают то же проще: const user = useAuth().
Где HOC уместен сегодня
Когда нужно управлять самим рендерингом: подменить компонент целиком, обернуть провайдером или Error Boundary, расширить чужой компонент без доступа к его коду. Плюс легаси-код.
Коротко для собеседования
HOC — функция «компонент → компонент», добавляющая поведение через обёртку (connect, React.memo). Правила: пробрасывать props и ref, задавать displayName, не создавать в рендере. После хуков используется редко — в основном для контроля рендеринга и в легаси; переиспользование логики делают кастомными хуками.