convert react js components into an html file

The main pieces are:

  • serializing the component DOM tree as HTML using Element.outerHTML (or Element.innerHTML if you’re sure that’s what you want) on a ref
  • creating a File from the HTML
  • initiating the download of the File

Here’s an example of how you could do it (adjust to your needs):

Note that, unfortunately, Stack Overflow doesn’t set allow-downloads on the sandbox attribute of the iframe used to render the live snippet demo (so the actual download won’t happen when you click a button). Copy + paste this example into an HTML file and run in a local dev server to see it working.

<div id="root"></div><script src="https://unpkg.com/[email protected]/umd/react.development.js"></script><script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">

const {useRef} = React;

function createHTMLFile (fileName: string, html: string): File {
  return new File([html], fileName, {type: 'text/html'});
}

function saveFile (file: File): void {
  const oUrl = URL.createObjectURL(file);
  const a = document.createElement('a');
  a.style.setProperty('display', 'none');
  a.href = oUrl;
  a.download = file.name;
  document.body.appendChild(a);
  a.click();
  a.remove();
  // 10s is arbitrary, but is more than enough for the user to download the HTML
  // even if they're preseneted with a download confirmation prompt by their
  // browser:
  const delay = 10_000;
  // the important part is that you clean up the object URL so that you don't
  // leak memory for every click (since they aren't garbage collected)
  setTimeout(() => URL.revokeObjectURL(oUrl), delay);
};

function Downloadable (props: { children?: React.ReactNode; }): React.ReactElement {
  const ref = useRef<HTMLDivElement>(null);

  const handleClick = () => {
    const div = ref.current;
    if (!div) return;
    const html = div.outerHTML;
    const fileName = `component.html`;
    saveFile(createHTMLFile(fileName, html));
  };

  return (
    <div>
      <button onClick={handleClick}>Download as HTML</button>
      <div {...{ref}}>{props.children}</div>
    </div>
  );
}

function Example (): React.ReactElement {
  return (
    <>
      <Downloadable>
        <header>
          <h1>hello world</h1>
          <p>description</p>
        </header>
      </Downloadable>
      <Downloadable>
        <h2>a list</h2>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </Downloadable>
    </>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));

</script>

TS Playground

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top