Skip to content

Instantly share code, notes, and snippets.

@sergiodxa
Last active January 4, 2024 16:11
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sergiodxa/e339cc18f34834871497ac35a1353f43 to your computer and use it in GitHub Desktop.
Save sergiodxa/e339cc18f34834871497ac35a1353f43 to your computer and use it in GitHub Desktop.
Dynamically generate a PDF with Remix
import { renderToStream } from "@react-pdf/renderer";
import ReactDOMServer from "react-dom/server";
import { EntryContext, Headers, RemixServer, Request, Response } from "remix";
import PDF, { loader } from "./pdfs/my-pdf.server";
async function handlePDFRequest(request: Request, headers: Headers) {
// get the data for the PDF
let response = await loader({ request, context: {}, params: {} });
// if it's a response return it, this means we redirected
if (response instanceof Response) return response;
// set the correct content-type
headers.set("Content-Type", "application/pdf");
// render the PDF to a stream
let stream = await renderToStream(<PDF {...response} />);
// wait for the stream to end and transform it to a Buffer
let body: Buffer = await new Promise((resolve, reject) => {
let buffers: Uint8Array[] = [];
stream.on("data", (data) => {
buffers.push(data);
});
stream.on("end", () => {
resolve(Buffer.concat(buffers));
});
stream.on("error", reject);
});
// renturn the response
return new Response(body, { status: 200, headers });
}
export default async function handleRequest(
request: Request,
status: number,
headers: Headers,
remixContext: EntryContext
) {
if (new URL(request.url).pathname === "/my-pdf.pdf") {
return await handlePDFRequest(request, headers);
}
headers.set("Content-Type", "text/html; charset=utf-8");
let markup = ReactDOMServer.renderToString(
<RemixServer context={remixContext} url={request.url} />
);
return new Response("<!DOCTYPE html>" + markup, { status, headers });
}
export let loader: LoaderFunction = async ({ request }) => {
let user = await authenticator.isAuthenticated(request);
if (!user) return redirect("/");
let data = await api(user.token).getDataForThePDF();
return { data }
};
export default function PDF({ data }: Props) {
return (
<Document title="Title">
<Page
size="A4"
style={{
paddingTop: 48,
paddingLeft: 72,
paddingRight: 48,
paddingBottom: 72,
}}
>
// here you can use data and React PDF components to generate the PDF
</Page>
</Document>
);
}
@kpwahn
Copy link

kpwahn commented Nov 3, 2022

I get build errors when importing the latest version of @react-pdf/renderer. How did you get around this?

@Njogu-Ndegwa
Copy link

Hello. I keep getting this error when I run this, 'Error: Some functionality, such as asynchronous I/O (fetch, Cache API, KV), timeouts (setTimeout, setInterval), and generating random values (crypto.getRandomValues, crypto.subtle.generateKey), can only be performed while handling a request.
at assertInRequest (C:\Users\llllllllllllll\shopify-hydrogen-storefront\node_modules.pnpm@miniflare+shared@2.14.0\node_modules@miniflare\shared\src\context.ts:51:11)
at C:\Users\llllllllllllll\shopify-hydrogen-storefront\node_modules.pnpm@miniflare+core@2.14.0\node_modules@miniflare\core\src\standards\timers.ts:15:28
at FSWatcher2._this._persist (C:\Users\llllllllllllll\shopify-hydrogen-storefront\dist\worker\node-modules-polyfills:fs:14384:24)
at FSWatcher2.start (C:\Users\llllllllllllll\shopify-hydrogen-storefront\dist\worker\node-modules-polyfills:fs:14424:14)
at Volume2.watch (C:\Users\llllllllllllll\shopify-hydrogen-storefront\dist\worker\node-modules-polyfills:fs:14070:15)
at watchStdo (C:\Users\llllllllllllll\shopify-hydrogen-storefront\dist\worker\node-modules-polyfills:fs:14563:7)
at C:\Users\llllllllllllll\shopify-hydrogen-storefront\dist\worker\node-modules-polyfills:fs:14558:1
at SourceTextModule.evaluate (node:internal/vm/module:224:23)
at VMScriptRunner.runAsModule (C:\Users\llllllllllllll\shopify-hydrogen-storefront\node_modules.pnpm@miniflare+runner-vm@2.14.0\node_modules@miniflare\runner-vm\src\index.ts:40:18)
at VMScriptRunner.run (C:\Users\llllllllllllll\shopify-hydrogen-storefront\node_modules.pnpm@miniflare+runner-vm@2.14.0\node_modules@miniflare\runner-vm\src\index.ts:86:17)' How did you get around it. Ps this is a hydrogen application

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment