Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке HOC?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Higher-Order Component (HOC)** - це **функція**, яка **приймає компонент як аргумент** і **повертає новий компонент**, додаючи йому додаткову поведінку або дані. **Ключове:** HOC - функція, що обгортає компонент, щоб "розширити" його функціональність.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротке визначення > **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 />; }; ``` 2. **Передавай** `props` **далі** Завжди прокидуй `...props`, щоб не втрачати передані властивості: ```javascript return <WrappedComponent {...props} />; ``` 3. **Зберігай читабельне ім'я компонента** У HOC часто роблять: ```javascript Enhanced.displayName = `withLogger(${WrappedComponent.displayName || WrappedComponent.name})`; ``` 4. **Не зловживай вкладеністю** Багато 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.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.