GregRos
GregRos

Reputation: 9113

Insert HTML comments in React

Is there a way to insert an HTML comment node in React JSX, in the same way you might insert a component or DOM node?

E.g., something like:

React.createElement(Comment, {}, "comment text");

Would render to:

<!-- comment text -->

The idea is that the comment be visible on the page, so { /* this /* } doesn't answer my question.

Note that the following related question doesn't have an answer and asks for something somewhat different:

How to render a HTML comment in React?

I just want to render a single comment node. I notice that React infrastructure renders HTML comments on its own, so perhaps there is a (slightly hacky?) way to do it too.

Upvotes: 23

Views: 8318

Answers (5)

Abbysssal
Abbysssal

Reputation: 36

I experimented a lot, trying to add comments in React, and discovered this work-around — you can use a <script> element that replaces itself with the comment. It's instant, and doesn't require a wrapper.

"use client";

export default function Comment({ text }) {
  if (typeof window === "undefined") {
    const code = `document.currentScript.outerHTML = "<!-- ${text} -->"`;
    return <script>{code}</script>;
  }
}
  • It happens instantly. When the browser loads the initial HTML, the script is immediately executed and replaced by a comment. If you keep reloading the page, you might see the <script> element flash in the DevTools for just a moment.

  • There are no hydration errors, since by the time React loads and hydrates the document, the script element is already replaced by a comment node. The client-render of <Comment> returns undefined, so there isn't anything for React to match it with, and it's simply ignored.

  • BUT: it only works when rendered from the server-side. You may need to tinker around a bit with client-rendering part, to get the state updates working properly. Getting a reference to the comment node will probably be a bit problematic here.

Well, it should be good enough for hiding easter eggs at least!


Also, here's a IE11-friendly version that doesn't have document.currentScript:

"use client";
import { useId } from "react";

export default function Comment({ text }) {
  if (typeof window !== "undefined") return;
  // eslint-disable-next-line react-hooks/rules-of-hooks
  const id = useId();

  const code = `document.getElementById("${id}").outerHTML = "<!-- ${text} -->"`;
  return <script id={id}>{code}</script>;
}

For a renderToStaticMarkup-compatible one (returns comments in the initial HTML, but leaves extraneous elements) see @zomars's answer under a different question.

Upvotes: 1

Harrie
Harrie

Reputation: 1

This solved it for me:

  • Create a ref
  • Create a dummy element and assign the ref to it
  • Create a comment element and put the props.children as content into it
  • Use useEffect to replace the dummy element by the generated comment when the element was mounted (useEffect is activated on element's mount)
import {useEffect, useRef} from "react";

export const HtmlComment = (props) => {

    const theRef = useRef(null)
    useEffect(() => {
        const comment = document.createComment(props.children);
    theRef.current.replaceWith(comment);

    }, []);
    return (
        <span ref={theRef}></span>
    );
};

And then use it like this:

<HtmlComment>
    Your Comment goes here
</HtmlComment>

Upvotes: 0

Stephen Foster
Stephen Foster

Reputation: 1

Yes, you can insert an HTML comment node in React JSX by using curly braces {} and JavaScript syntax. Here's an example:

import React from 'react';

const MyComponent = () => {
  return (
    <div>
      {/* This is an HTML comment */}
      <p>Some content</p>
    </div>
  );
};

export default MyComponent;

In the code snippet above, the HTML comment This is an HTML comment is inserted using the curly braces and the JavaScript-style comment syntax ({/* ... */}). The comment will be rendered as a regular HTML comment in the resulting HTML markup.

Please note that HTML comments are generally used for developer notes or to temporarily remove or hide parts of the code. They are not meant to be used as a way to pass data or communicate with the application logic.

Upvotes: -3

ptim
ptim

Reputation: 15587

Another alternative is to use dangerouslySetInnerHTML

<div dangerouslySetInnerHTML={{ __html: '<!-- comment text -->' }} />

dangerouslySetInnerHTML is React's replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it's dangerous.

https://facebook.github.io/react/docs/dom-elements.html#dangerouslysetinnerhtml

Upvotes: 6

StackOverMySoul
StackOverMySoul

Reputation: 2037

Only thing I could think of would be to manipulate the DOM on componentDidMount and add your comment there, but then React wouldn't be handling that DOM manipulation so it might cause some issues?

    var HTMLComment = React.createClass({

      componentDidMount: function(){
        var htmlComment = "<!--" + this.props.comment + "-->"; 
          this.span.innerHTML = htmlComment;
      },

      render: function(){
        return (
            <span ref={(span) => this.span = span} ></span>
        )
      }
    })

Upvotes: 4

Related Questions