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.