Skip to content

Instantly share code, notes, and snippets.

@mendes5
Created August 22, 2023 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mendes5/6ed96f3be95eacdce9d006f3ecbf6a01 to your computer and use it in GitHub Desktop.
Save mendes5/6ed96f3be95eacdce9d006f3ecbf6a01 to your computer and use it in GitHub Desktop.
Allows to print a JSX subtree, usefull for export as PDF functionality.
const useExport = (tree, documentTitle, ready) => {
const containerRef = useRef(null);
const frameRef = useRef();
const [readyToExport, setReadyToExport] = useState(false);
useEffect(() => {
if (!ready) return;
const sheet = new ServerStyleSheet();
const out = ReactDOM.renderToString(
sheet.collectStyles(
<ThemeProvider>
<html lang="en">
<head>
<title>{documentTitle}</title>
</head>
<body>{tree}</body>
</html>
</ThemeProvider>
)
);
const domParser = new DOMParser();
const dom = domParser.parseFromString(out, 'text/html');
const css = sheet.instance.toString();
const style = document.createElement('style');
style.innerHTML = css;
dom.head.appendChild(style);
const xml = new XMLSerializer().serializeToString(dom);
const frame = document.createElement('iframe');
frame.setAttribute('srcdoc', xml);
frameRef.current = frame;
if (containerRef.current) {
containerRef.current?.appendChild(frame);
requestAnimationFrame(() => {
setReadyToExport(true);
});
}
return () => {
frameRef.current = null;
frame.remove();
};
}, [documentTitle, tree]);
return {
exportDocument: () => frameRef.current.contentWindow?.print(),
readyToExport,
containerRef,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment