';\n \n return (\n
\n {text}\n
\n );\n // Выведет: как текст, не код\n}\n\n// HTML сущности\nfunction HtmlEntities() {\n const html = 'A   B — C';\n return (\n
\n );\n // Выведет: A B - C\n}\n```\n\n## 8. Правильная обработка событий\n\n```javascript\nfunction HtmlWithEvents() {\n const html = '';\n \n // Плохо: onclick не будет работать\n return (\n
\n );\n \n // Хорошо: использовать React события\n return (\n \n );\n}\n```\n\n## Чеклист безопасности\n\n- Санитизируйте пользовательский контент с DOMPurify\n- Не используйте dangerouslySetInnerHTML с внешним контентом\n- Проверяйте origin при загрузке HTML из API\n- Установите Content Security Policy (CSP)\n- Используйте html-react-parser для более сложных случаев\n- Предпочитайте JSX структурированному HTML\n\n## Сравнение методов\n\n| Метод | Безопасность | Интерактивность | Производительность |\n|-------|-------------|-----------------|-------------------|\n| dangerouslySetInnerHTML | Низкая без санитизации | Нет | Хорошая |\n| html-react-parser | Зависит от реализации | Да | Хорошая |\n| ReactMarkdown | Хорошая | Да | Средняя |\n| JSX структурированно | Отличная | Да | Отличная |\n\nВсегда выбирайте метод, соответствующий вашему случаю использования.","dateCreated":"2026-04-03T17:52:42.175941","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как отрендерить html в JSX?

1.7 Middle🔥 191 комментариев
#JavaScript Core#Браузер и сетевые технологии

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Рендеринг HTML в JSX

В React/JSX существует несколько способов для вставки HTML кода. Каждый подход имеет свои особенности, преимущества и недостатки. Рассмотрим все основные методы и когда их использовать.

1. dangerouslySetInnerHTML

Основной способ вставки сырого HTML в React:

function HtmlContent() {
  const htmlString = '<p>Hello <strong>World</strong></p>';
  
  return (
    <div dangerouslySetInnerHTML={{ __html: htmlString }} />
  );
}

Название dangerouslySetInnerHTML намеренно пугающее - это предупреждение о проблемах безопасности. Его нужно использовать с осторожностью.

Когда использовать:

  • Контент из доверенного источника (ваша база данных)
  • Markdown, конвертированный в HTML
  • HTML из CMS, который вы контролируете

Потенциальные проблемы:

  • XSS атаки при использовании пользовательского ввода
  • Потеря интерактивности React компонентов внутри HTML

2. Безопасная вставка с санитизацией

Для пользовательского контента используйте санитизацию:

import DOMPurify from 'dompurify';

function SafeHtml({ userContent }) {
  const sanitized = DOMPurify.sanitize(userContent);
  
  return (
    <div dangerouslySetInnerHTML={{ __html: sanitized }} />
  );
}

// Использование
<SafeHtml userContent="<p>Safe text</p>" />

DOMPurify удаляет потенциально опасные теги и атрибуты:

const dirty = '<img src=x onerror="alert(1)">'; // XSS
const clean = DOMPurify.sanitize(dirty);
// clean = '<img src="x">'

3. Использование библиотеки html-react-parser

Больше контроля над парсингом HTML:

import parse from 'html-react-parser';

function ParsedContent() {
  const html = '<p>Hello <strong>World</strong></p>';
  
  return (
    <div>
      {parse(html)}
    </div>
  );
}

// С преобразованием элементов
function CustomParsedContent({ html }) {
  const options = {
    replace: (domNode) => {
      if (domNode.name === 'img') {
        return (
          <img
            src={domNode.attribs.src}
            alt={domNode.attribs.alt}
            className="max-w-full"
          />
        );
      }
      if (domNode.name === 'a') {
        return (
          <a
            href={domNode.attribs.href}
            target="_blank"
            rel="noopener noreferrer"
          >
            {domNode.children}
          </a>
        );
      }
    }
  };
  
  return <div>{parse(html, options)}</div>;
}

4. Преобразование Markdown в JSX

Для контента на Markdown используйте специализированные библиотеки:

import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';

function MarkdownContent({ markdown }) {
  return (
    <ReactMarkdown
      components={{
        code({ node, inline, className, children, ...props }) {
          const language = className?.replace(/language-/, '');
          return !inline ? (
            <SyntaxHighlighter language={language} {...props}>
              {String(children).replace(/\n$/, '')}
            </SyntaxHighlighter>
          ) : (
            <code className={className} {...props}>
              {children}
            </code>
          );
        },
        h1: ({ node, ...props }) => <h1 className="text-3xl font-bold" {...props} />,
        a: ({ node, ...props }) => (
          <a className="text-blue-500 underline" target="_blank" {...props} />
        )
      }}
    >
      {markdown}
    </ReactMarkdown>
  );
}

5. Создание сложного HTML структурированно

Когда HTML структурирован, лучше использовать JSX:

function BlogPost({ title, content, author }) {
  return (
    <article className="blog-post">
      <header>
        <h1>{title}</h1>
        <p className="author">By {author}</p>
      </header>
      <section className="content">
        {content}
      </section>
      <footer>
        <p>Published on {new Date().toLocaleDateString()}</p>
      </footer>
    </article>
  );
}

Этот подход более безопасен и легче для оптимизации.

6. HTML с интерактивностью React

Если вам нужны React компоненты внутри HTML:

function InteractiveContent() {
  const [count, setCount] = useState(0);
  
  // Лучше: структурировать в JSX
  return (
    <div className="content">
      <p>This is HTML content</p>
      <button onClick={() => setCount(count + 1)}>
        Clicked {count} times
      </button>
    </div>
  );
}

// Или парсить и заменять элементы
function HtmlWithButtons({ html }) {
  return parse(html, {
    replace: (domNode) => {
      if (domNode.attribs?.['data-interactive']) {
        return (
          <InteractiveButton key={domNode.attribs.id}>
            {domNode.children}
          </InteractiveButton>
        );
      }
    }
  });
}

7. Обработка специальных символов

function TextWithEntities() {
  // Автоматическое экранирование в JSX
  const text = '<script>alert(1)</script>';
  
  return (
    <div>
      {text}
    </div>
  );
  // Выведет: <script>alert(1)</script> как текст, не код
}

// HTML сущности
function HtmlEntities() {
  const html = 'A &nbsp; B &mdash; C';
  return (
    <div dangerouslySetInnerHTML={{ __html: html }} />
  );
  // Выведет: A   B - C
}

8. Правильная обработка событий

function HtmlWithEvents() {
  const html = '<button onclick="alert(1)">Click me</button>';
  
  // Плохо: onclick не будет работать
  return (
    <div dangerouslySetInnerHTML={{ __html: html }} />
  );
  
  // Хорошо: использовать React события
  return (
    <button onClick={() => alert('Clicked')}>
      Click me
    </button>
  );
}

Чеклист безопасности

  • Санитизируйте пользовательский контент с DOMPurify
  • Не используйте dangerouslySetInnerHTML с внешним контентом
  • Проверяйте origin при загрузке HTML из API
  • Установите Content Security Policy (CSP)
  • Используйте html-react-parser для более сложных случаев
  • Предпочитайте JSX структурированному HTML

Сравнение методов

МетодБезопасностьИнтерактивностьПроизводительность
dangerouslySetInnerHTMLНизкая без санитизацииНетХорошая
html-react-parserЗависит от реализацииДаХорошая
ReactMarkdownХорошаяДаСредняя
JSX структурированноОтличнаяДаОтличная

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

Как отрендерить html в JSX? | PrepBro