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

Компоненты высшего порядка (HOC, Higher-Order Components) в контексте MDX представляют собой функции, которые принимают компонент React и возвращают новый компонент с расширенной функциональностью. Это ключевой инструмент для повторного использования логики и стилизации компонентов внутри MDX-документов.


Основная концепция HOC

HOC можно представить как фабрику компонентов. Она оборачивает исходный компонент, добавляя к нему дополнительные пропсы, состояние или побочные эффекты, не изменяя исходный код компонента напрямую. В MDX это позволяет легко управлять внешним видом и поведением компонентов, используемых в документации, статьях или интерактивных руководствах.

Пример базового HOC:

import React from 'react';

function withHighlight(WrappedComponent) {
  return function Highlighted(props) {
    return (
      <div style={{ backgroundColor: 'yellow' }}>
        <WrappedComponent {...props} />
      </div>
    );
  };
}

Здесь withHighlight принимает компонент и возвращает новый, который оборачивает исходный компонент в <div> с подсветкой. В MDX это удобно для выделения важных блоков кода или текста.


Использование HOC в MDX

MDX позволяет импортировать и использовать React-компоненты непосредственно в разметке. HOC можно применять как к компонентам MDX, так и к пользовательским компонентам, импортируемым из библиотеки.

Пример интеграции HOC с MDX-компонентом:

import { Note } from './components/Note';
import { withHighlight } from './hocs/withHighlight';

const HighlightedNote = withHighlight(Note);

export default function Page() {
  return (
    <>
      <HighlightedNote>
        Важная заметка с подсветкой.
      </HighlightedNote>
    </>
  );
}

В данном примере Note — обычный компонент для отображения заметки, а HOC withHighlight добавляет визуальное выделение.


Передача пропсов через HOC

HOC может расширять исходный компонент, добавляя новые пропсы или изменяя существующие. Важно учитывать прозрачную передачу пропсов, чтобы исходный компонент сохранял возможность работать с внешними данными.

Пример расширенного HOC с пропсами:

function withTheme(WrappedComponent, theme) {
  return function ThemedComponent(props) {
    return <WrappedComponent {...props} style={{ color: theme.color, background: theme.background }} />;
  };
}

const DarkNote = withTheme(Note, { color: 'white', background: 'black' });

Здесь HOC withTheme принимает дополнительный параметр theme и передает стили компоненту, сохраняя при этом все оригинальные пропсы через {...props}.


Комбинирование нескольких HOC

В больших проектах часто возникает необходимость применения сразу нескольких HOC к одному компоненту. Существует подход композиции HOC, при котором каждый HOC оборачивает предыдущий:

import { compose } from 'redux';

const EnhancedNote = compose(
  withHighlight,
  withTheme.bind(null, { color: 'white', background: 'black' })
)(Note);

Метод compose обеспечивает последовательное применение HOC, что делает код компактным и читаемым. В MDX это полезно для добавления нескольких визуальных эффектов к компонентам документации.


HOC и MDX-плагины

MDX предоставляет возможность использовать HOC для обертки всех стандартных компонентов Markdown. Например, можно заменить стандартный h1, p или code на кастомные компоненты с расширенной функциональностью:

import { MDXProvider } from '@mdx-js/react';
import { withHighlight } from './hocs/withHighlight';

const components = {
  p: withHighlight(({ children }) => <p>{children}</p>),
};

export default function MDXWrapper({ children }) {
  return <MDXProvider components={components}>{children}</MDXProvider>;
}

Этот подход позволяет глобально применять стили и поведение ко всем компонентам Markdown, что значительно упрощает поддержку единого стиля документации.


Ограничения и рекомендации

  • HOC не должны модифицировать исходный компонент напрямую, чтобы не нарушать принцип чистоты и повторного использования.
  • Для сложных HOC, которые управляют состоянием, рекомендуется использовать функциональные компоненты и хуки, чтобы сохранить совместимость с современным React.
  • В MDX важно контролировать передачу пропсов, чтобы кастомные компоненты корректно отображались внутри документации и не ломали стандартную разметку Markdown.

Полезные паттерны HOC в MDX

  1. Стилизация компонентов Markdown: оборачивать заголовки, параграфы и блоки кода для поддержания единого дизайна.
  2. Добавление аналитики: автоматически отслеживать клики или просмотры компонентов в документации.
  3. Логика авторизации/доступа: скрывать или показывать контент на основе прав пользователя.
  4. Повторное использование интерактивных блоков: компоненты с кнопками, всплывающими подсказками, модальными окнами.

HOC в MDX превращают документацию и статьи в динамичные, интерактивные и визуально согласованные приложения, обеспечивая при этом повторное использование кода и единообразие стиля.