PassFront
  1. PassFront
  2. База знаний
  3. Паттерны и подходы

Приведи пример 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).

Другие вопросы раздела