Как сделать комментарий HTML в React?

В настоящее время метод render может возвращать только один элемент/компонент. См.: здесь

В обсуждении в этом билете некоторые предлагают обернуть несколько элементов, возвращенных из компонента React в комментарии HTML, чтобы браузер не проигнорировал компонент упаковки, например:

<A>
    <B></B>
    <Fragment>
        <C></C>
        <D></D>
    </Fragment>
    <E></E>
</A>

выдаст:

<a>
    <b></b>
    <!--<fragment data-reactid="">-->
        <c></c>
        <d></d>
    <!--</fragment>-->
    <e></e>
</a>

Но как на самом деле создать компонент, который отображает только HTML-комментарий? Другими словами, как выглядела бы функция рендеринга компонента "фрагмент" в приведенном выше примере?

Ответ 1

Вот что я получил в одном из моих последних проектов:

import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';

class ReactComment extends Component {
    static propTypes = {
        text: PropTypes.string,
        trim: PropTypes.bool
    };

    static defaultProps = {
        trim: true
    };

    componentDidMount() {
        let el = ReactDOM.findDOMNode(this);
        ReactDOM.unmountComponentAtNode(el);
        el.outerHTML = this.createComment();
    }

    createComment() {
        let text = this.props.text;

        if (this.props.trim) {
            text = text.trim();
        }

        return `<!-- ${text} -->`;
    }

    render() {
        return <div />;
    }
}

export default ReactComment;

Итак, вы можете использовать его следующим образом:

<A>
    <B></B>
    <ReactComment text="<fragment>" />
        <C></C>
        <D></D>
     <ReactComment text="</fragment>" />
    <E></E>
</A>

Ответ 2

То, как вы планируете это делать, не будет работать с простым решением для решения ванили. Однако вы можете определить пользовательский веб-компонент, который преобразуется в комментарии HTML и возвращает это из оболочки React. Примерный компонент реализован здесь. Для использования в React см. этот URL.

Обновление 19/01/2017

Итак, это непроверенная теория, но веб-компонент может быть чем-то вроде -

`` `

 /**
 * <react-comment-sentinel> Web Component
 *
 * @usage
 *  <react-comment-sentinel sentinel="fragment"><div>Hello there!</div></react-comment-sentinel>

 * @result
 *  <!-- <fragment> --><div>Hello there!</div><!-- </fragment> -->
 */
var proto = Object.create(HTMLElement.prototype, {
 name: { get: function() { return 'React HTML Comment'; } },
 createdCallback: { value: function() {

  /**
   * Firefox fix, is="null" prevents attachedCallback
   * @link https://github.com/WebReflection/document-register-element/issues/22
   */
  this.is = '';
  this.removeAttribute('is');
 } },
 attachedCallback: { value: function() {
  var tag = this.attributes("sentinel");
  this.outerHTML = '<!-- <' + tag + '> -->' + this.innerHtml + '<!-- </' + tag + '> -->';
 } }
});
document.registerElement('react-comment-sentinel', { prototype: proto });

`` `

Обратите внимание, что внутренние дети - это простой html, а не React. Тем не менее, вы можете поэкспериментировать с расширением кода поддержка React Components.

Ответ 3

Предполагая, что вы работаете в React 16. 8+ вы можете использовать небольшой функциональный компонент, который позволяет вам предоставить текстовое свойство и сделать HTML-комментарий.

import React, {useEffect, useRef} from 'react';

const ReactComment = ( props ) => {
    const el = useRef();
    useEffect( () => {
        el.current.outerHTML = '<!-- ${props.text} -->';
    }, [] );
    return (
        <div ref={el}/>
    );
};

export default ReactComment;

Затем вы можете использовать его так

<A>
    <B></B>
    <ReactComment text="<fragment>" />
        <C></C>
        <D></D>
     <ReactComment text="</fragment>" />
    <E></E>
</A>

Ответ 4

Вот еще один новаторский подход, если вам нужно это для работы с SSR.

Здесь компонент MaxWidth я использую с моим почтовым инструментом Myza.

import ReactDOMServer from 'react-dom/server'

export const MaxWidth = ({ maxWidth = 0, className, children }: IMaxWidthProps) => {
  const renderedChildren = ReactDOMServer.renderToStaticMarkup(
    <div className={className} style={{ maxWidth: '${maxWidth}px', margin: '0 auto' }}>
      {children}
    </div>
  )

  return <div dangerouslySetInnerHTML={{
    __html: '
    <!--[if mso]><center><table><tr><td width="${maxWidth}"><![endif]-->
    ${renderedChildren}
    <!--[if mso]> </td></tr></table></center><![endif]-->
  ' }}
  />
}

Ответ 5

Изменить: Для тех, кто нашел этот ответ полезным, зацените этот ответ вместо этого!

Опубликованная проблема не требует стиля комментария в React!


Используйте фигурные скобки, так что вы можете использовать комментарий javascript /* */.

<a>
    <b></b>
    {/*<fragment data-reactid="">*/}
        <c></c>
        <d></d>
    {/*</fragment>*/}
    <e></e>
</a>