Компоненты высшего порядка (Higher-Order Components, HOC) представляют собой функцию, которая принимает компонент и возвращает новый компонент с расширенной функциональностью. Этот подход позволяет повторно использовать логику между компонентами без дублирования кода, сохраняя при этом чистоту и декларативность.
HOC можно рассматривать как паттерн композиции. Он не изменяет исходный компонент напрямую, а создает обертку, которая добавляет новые свойства, состояние или обработку событий. Простейшая форма HOC выглядит так:
import { h } from 'preact';
function withExtraProps(WrappedComponent) {
return function EnhancedComponent(props) {
const newProps = { ...props, extra: 'value' };
return <WrappedComponent {...newProps} />;
};
}
В этом примере withExtraProps принимает компонент
WrappedComponent и возвращает новый компонент
EnhancedComponent, который добавляет дополнительное
свойство extra.
Ключевые моменты:
import { h } from 'preact';
import { useState } from 'preact/hooks';
function withCounter(WrappedComponent) {
return function CounterComponent(props) {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return <WrappedComponent {...props} count={count} increment={increment} />;
};
}
Такой HOC позволяет любому компоненту получать счетчик и функцию для его увеличения без необходимости самостоятельно реализовывать состояние.
function withLogging(WrappedComponent) {
return function LoggingComponent(props) {
console.log('Rendering component with props:', props);
return <WrappedComponent {...props} />;
};
}
HOC можно использовать для отладки и анализа рендеров без изменения логики самого компонента.
При использовании HOC важно корректно передавать пропсы: исходные
свойства компонента должны сохраняться. Паттерн ...props
обеспечивает прозрачную передачу:
function withTheme(WrappedComponent) {
return function ThemedComponent(props) {
const theme = { color: 'blue', fontSize: 16 };
return <WrappedComponent {...props} theme={theme} />;
};
}
Если HOC должен модифицировать часть пропсов, рекомендуется делать это явно, чтобы избежать неожиданных конфликтов.
Несколько HOC можно комбинировать через цепочку вызовов:
const EnhancedComponent = withLogging(withCounter(MyComponent));
В этом случае сначала применяется withCounter, а затем
withLogging. Порядок важен, так как HOC получают пропсы от
предыдущего уровня.
Для упрощения композиции часто используют функцию
compose:
const compose = (...hocs) => Component =>
hocs.reduceRight((acc, hoc) => hoc(acc), Component);
const EnhancedComponent = compose(withLogging, withCounter)(MyComponent);
ref), так как обертка скрывает внутренний компонент. Для
работы с рефами применяют forwardRef.HOC часто полезны, когда требуется многоразовое обогащение логики сразу для нескольких компонентов, тогда как хуки более подходят для локального состояния и функциональных компонентов.
...props.Использование HOC в Preact позволяет создавать масштабируемую архитектуру компонентов, облегчает повторное использование логики и поддерживает декларативный стиль программирования, характерный для современного фронтенда.