Приведи пример HOC.
Паттерны и подходы
HOC — функция, которая принимает компонент и возвращает новый, с добавленным поведением. Вот рабочий пример.
Пример: withAuth — защита компонента
const withAuth = (Component) => {
const WithAuth = (props) => {
const { user, isLoading } = useCurrentUser();
if (isLoading) return <Spinner />;
if (!user) return <Navigate to="/login" replace />;
return <Component {...props} user={user} />; // пробрасываем props + добавляем user
};
WithAuth.displayName = `withAuth(${Component.displayName ?? Component.name})`;
return WithAuth;
};
// использование
const Dashboard = withAuth(DashboardInner);HOC решает три задачи разом: показывает загрузку, редиректит неавторизованных, прокидывает user — и всё это без изменения кода DashboardInner.
Пример попроще: withLogger
const withLogger = (Component) => (props) => {
useEffect(() => {
console.log(`${Component.name} mounted`, props);
}, []);
return <Component {...props} />;
};Обязательные детали
- Пробрасывать все props (
{...props}), при необходимости — ref через forwardRef. - Задавать displayName, иначе в DevTools будет безымянная обёртка.
- Не вызывать HOC в рендере (
const C = withAuth(Inner)внутри компонента): каждый рендер даст новый тип и пересоздание поддерева.
Современная альтернатива
Тот же результат хуком — без обёртки:
const Dashboard = () => {
const user = useRequireAuth(); // редирект/загрузка внутри хука
return <DashboardInner user={user} />;
};Коротко для собеседования
Пример — withAuth: HOC оборачивает компонент, показывает спиннер при загрузке, редиректит неавторизованных и прокидывает user через props. HOC должен пробрасывать props и задавать displayName, и его нельзя создавать внутри рендера. Сегодня такую задачу чаще решают кастомным хуком (useRequireAuth).