React - отличный инструмент не только для HTML, но и для безопасного и эргономичного создания любого документа на основе XML. Фактически, мы использовали немного больше, чем React + SVG, чтобы построить весь редактор топо-кода в Boltline:

JSX ≠ HTML

Однако есть пара вещей, которые очень важно помнить при использовании React для XML. Несмотря на «разметку» JSX, на самом деле вы создаете не строки, а объект JS; поля не обязательно соответствуют атрибутам HTML, но относятся к свойствам DOM или свойствам React, основанным на DOM. Вот почему вы используете className вместо class.

Поэтому, когда вам нужно добавить xlink:href="https://example.com", вы захотите использовать xlinkHref="https://example.com" (обратите внимание на camelCase).

Это отлично подходит для поддерживаемых атрибутов, которые включают практически все, что вам нужно для SVG.

JSX ≠ XML

Однако это перестает работать, когда вам нужны более продвинутые функции XML. JSX совершенно ясно, что его цель - не полной поддержки XML. Давайте попробуем добавить расширение изображений Google в наш файл sitemap.xml, созданный с помощью реакции:

...
<image:image>
  <image:loc>http://example.com/image.jpg</image:loc>
</image:image>
...

Это ломается с очень явной ошибкой:

ERROR in ./SitemapXMLRoot.js
Module build failed: SyntaxError: Namespace tags are not supported. ReactJSX is not XML.
> 181 |  <image:image>
      |   ^
  182 |    <image:loc>http://example.com/image.jpg</image:loc>
  183 |  </image:image>

Хотя JSX не справляется с этой задачей, на самом деле React справляется! Мы можем пойти дальше и использовать необработанные React.createElement вызовы для создания пользовательских компонентов React, готовых к JSX, которые отображают наши пользовательские элементы XML:

const ImageImage = (p: *) => {
  const { children, ...props } = p;
  return React.createElement("image:image", props, children);
};
const ImageLoc = (p: *) => {
  const { children, ...props } = p;
  return React.createElement("image:loc", props, children);
};

А теперь воспользуемся ими:

...
<ImageImage>
  <ImageLoc>http://example.com/image.jpg</ImageLoc>
</ImageImage>
...

И это работает! Это отображает наши элементы image:image и image:loc, как мы и хотели:

И еще кое-что.

Мы еще не определили пространство имен image:. Хотя React 16+ будет передавать настраиваемые атрибуты, двоеточие нарушает синтаксис JSX. Это легко обойти с помощью оператора распространения JSX:

const namespaces = {
  "xmlns:image": "http://www.google.com/schemas/sitemap-image/1.1"
};
<urlset
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  {...namespaces}
>

Посетите страницу React, посвященную элементам DOM, чтобы узнать больше!