Next.js Discord

Discord Forum
${html}

Is it possible to insert HTML string into Head?

Answered
White-chinned Petrel posted this in #help-forum
Open in Discord
White-chinned PetrelOP
I get HTML rendered as a string from a trusted server that includes link and script tags which I want to insert in Head (and in body too, which is probably the same problem).

I have tried to wrap it in script and div using dangerouslySetInnerHtml already and don't have any other ideas.

My best shot now is probably to use some third-party package that can parse HTML into React elements, which is not ideal.

Any help is appreciated 🙏
Answered by joulev
I have this same problem at work too. After many many attempts, we found that this is the only way to make it work:

"use client";

import parse, { Element, Text } from "html-react-parser";
import { useEffect, useState } from "react";

export function CustomHtml({ customHtml }: { customHtml: string }) {
  const [isMounted, setIsMounted] = useState(false);
  useEffect(() => setIsMounted(true), []);
  if (!isMounted) return null;
  return parse(customHtml, {
    // https://github.com/remarkablemark/html-react-parser/issues/98
    replace: domNode => {
      if (!(domNode instanceof Element)) return;
      // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- How to fix it then?
      if (domNode.type === "script") {
        const script = document.createElement("script");
        for (const key in domNode.attribs) script.setAttribute(key, domNode.attribs[key]);
        if (domNode.children.length !== 0 && domNode.children[0] instanceof Text)
          script.innerHTML = domNode.children[0].data;
        document.head.appendChild(script);
      }
    },
  });
}


All other methods we could think of, such as
;<script
  dangerouslySetInnerHtml={{
    __html: `</script>${html}<script>`,
  }}
/>

don’t work, one way or another.
View full answer

2 Replies

@White-chinned Petrel I get HTML rendered as a string from a trusted server that includes link and script tags which I want to insert in Head (and in body too, which is probably the same problem). I have tried to wrap it in script and div using dangerouslySetInnerHtml already and don't have any other ideas. My best shot now is probably to use some third-party package that can parse HTML into React elements, which is not ideal. Any help is appreciated 🙏
I have this same problem at work too. After many many attempts, we found that this is the only way to make it work:

"use client";

import parse, { Element, Text } from "html-react-parser";
import { useEffect, useState } from "react";

export function CustomHtml({ customHtml }: { customHtml: string }) {
  const [isMounted, setIsMounted] = useState(false);
  useEffect(() => setIsMounted(true), []);
  if (!isMounted) return null;
  return parse(customHtml, {
    // https://github.com/remarkablemark/html-react-parser/issues/98
    replace: domNode => {
      if (!(domNode instanceof Element)) return;
      // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- How to fix it then?
      if (domNode.type === "script") {
        const script = document.createElement("script");
        for (const key in domNode.attribs) script.setAttribute(key, domNode.attribs[key]);
        if (domNode.children.length !== 0 && domNode.children[0] instanceof Text)
          script.innerHTML = domNode.children[0].data;
        document.head.appendChild(script);
      }
    },
  });
}


All other methods we could think of, such as
;<script
  dangerouslySetInnerHtml={{
    __html: `</script>${html}<script>`,
  }}
/>

don’t work, one way or another.
Answer