0Pricing
Frontend Academy · Урок

Свойства рендеринга и шаблоны HOC

Передавайте функцию рендеринга как свойство для внедрения пользовательского интерфейса и оборачивайте компоненты в компоненты высшего порядка, чтобы внедрять поведение без изменения оригинала

«Свойства рендеринга и шаблоны HOC» — бесплатный урок Frontend Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.

Два классических шаблона повторного использования

До появления хуков (React 16.8) повторное использование логики с состоянием означало выбор между компонентами высшего порядка (HOC) и свойствами рендеринга. В новом коде они встречаются редко, но Вы по-прежнему встретите их в устаревших кодовых базах и многих библиотеках.

Свойства рендеринга — идея

Компонент принимает функцию в качестве свойства (обычно с именем render или children) и вызывает её с внутренним состоянием. Пользователь компонента решает, что отрисовать с этим состоянием.

function Mouse({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return render(pos);
}

// Usage:
<Mouse render={({ x, y }) => <p>{x}, {y}</p>} />

children как функция

Свойство children также может быть функцией — тот же шаблон с более чистым JSX.

function Mouse({ children }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  /* ... */
  return children(pos);
}

<Mouse>
  {({ x, y }) => <p>{x}, {y}</p>}
</Mouse>

Компоненты высшего порядка — идея

HOC — это функция, которая принимает компонент и возвращает новый компонент с дополнительными свойствами или поведением. Этот подход активно использовался в Redux через connect() и в React Router через withRouter().

function withMouse(Component) {
  return function WithMouse(props) {
    const [pos, setPos] = useState({ x: 0, y: 0 });
    useEffect(() => {
      const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
      window.addEventListener('mousemove', handler);
      return () => window.removeEventListener('mousemove', handler);
    }, []);
    return <Component {...props} mouse={pos} />;
  };
}

// Usage:
const Position = ({ mouse }) => <p>{mouse.x}, {mouse.y}</p>;
const EnhancedPosition = withMouse(Position);
<EnhancedPosition />

HOC объединяются обёртыванием

Можно выстроить несколько HOC в цепочку, но они образуют «ад обёрток», в котором сложно искать ошибки.

// Multiple HOCs:
const Enhanced = withRouter(connect(mapState)(withTranslation()(MyComponent)));
// Equivalent in modern React:
// const Enhanced = MyComponent (reads from hooks: useRouter, useSelector, useTranslation)

Свойства рендеринга и HOC

Свойства рендеринга: более явные, удобные для типизации, без конфликтов имён. HOC: более декларативные; без осторожности обёрнутые компоненты теряют статические типы, также возможны конфликты имён свойств.

Почему хуки заменили оба подхода

Пользовательские хуки достигают той же цели с меньшим количеством служебного кода: без компонентов-обёрток, вложенных аргументов-функций и сложных манипуляций с типами. В 2025 году хуки — идиоматичный подход.

// Custom hook equivalent of useMouse:
function useMouse() {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return pos;
}

// Usage:
const { x, y } = useMouse();

Когда свойства рендеринга всё ещё лучше

Для компонентов, которым нужно добавлять разметку, а не только состояние, например для виртуализированных списков, отрисовывающих элементы в определённых позициях, свойства рендеринга по-прежнему подходят лучше всего.

function VirtualList({ items, itemHeight, renderItem }) {
  const [scrollTop, setScrollTop] = useState(0);
  const start = Math.floor(scrollTop / itemHeight);
  const visible = items.slice(start, start + 20);
  return visible.map((item, i) => renderItem(item, start + i));
}

<VirtualList items={data} itemHeight={40} renderItem={(item, i) => (
  <Row key={i} data={item} />
)} />

Рекомендации по HOC при необходимости

Если необходимо написать HOC: копируйте статические методы (hoist-non-react-statics), передавайте ссылки (React.forwardRef) и сохраняйте displayName для DevTools.

Передача ссылок в HOC

По умолчанию HOC скрывают ссылки — используйте forwardRef, чтобы пользователи по-прежнему могли обращаться к ссылке базового компонента.

function withLogger(Component) {
  const Wrapped = React.forwardRef((props, ref) => {
    console.log('rendering', Component.name);
    return <Component {...props} ref={ref} />;
  });
  Wrapped.displayName = `withLogger(${Component.name})`;
  return Wrapped;
}

Как распознать устаревшие шаблоны

Вы встретите HOC и свойства рендеринга в react-redux (старый API), Apollo Client v2, react-router v5 (withRouter), Formik (Field) и styled-components (withTheme). Переписывайте их с использованием хуков, когда новые API этих библиотек это позволяют.

Быстрая проверка

Какой шаблон хуки в основном заменили для совместного использования логики с состоянием между компонентами React?

Итоги: свойства рендеринга и HOC

Свойства рендеринга: функция в качестве свойства, возвращающая JSX; явный и удобный для типизации подход. HOC: функция, оборачивающая компонент; используется старыми библиотеками (connect, withRouter). Пользовательские хуки заменили оба подхода для логики состояния. Свойства рендеринга по-прежнему лучше, когда нужно добавлять пользовательскую разметку (виртуализированные списки). При написании HOC: используйте forwardRef, переносите статические свойства и задавайте displayName.

Часто задаваемые вопросы

Урок «Свойства рендеринга и шаблоны HOC» бесплатный?

Да — полный текст урока «Свойства рендеринга и шаблоны HOC» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.

Чему я научусь в уроке «Свойства рендеринга и шаблоны HOC»?

Передавайте функцию рендеринга как свойство для внедрения пользовательского интерфейса и оборачивайте компоненты в компоненты высшего порядка, чтобы внедрять поведение без изменения оригинала Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Frontend Academy?

Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Свойства рендеринга и шаблоны HOC»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Frontend Academy?

Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Составные компоненты с Context
  2. Свойства рендеринга и шаблоны HOC
  3. Порталы для модальных окон и подсказок
  4. Границы ошибок
← Назад к Frontend Academy