Creating a PDF with React in the Browser

If you need to generate a PDF for your users, maybe some reports or a document you want users to be able to download, and if you know how to use React, you can generate a PDF in the browser directly using the framework you already know and probably use.

First you need to install @react-pdf/renderer as a dependency:

yarn add @react-pdf/renderer

Now, you can use it in your code by importing the different components the library provides:

import {
  Document,
  Page,
  PDFViewer,
  StyleSheet,
  Text,
  View,
} from "@react-pdf/renderer";

A short description of each one:

Document create a new PDF document, inside this you will place the pages and elements of a page. Page create a new page inside a document, a page can be automatically split on multiple pages if the page size is too big. And you manually add a new one if you want to force a new page.

PDFViewer is used to render your PDF document directly inside a React application.

StyleSheet is the same as the React Native StyleSheet API, you use it to create the styles you want to use on the elements of a PDF. Text is used to render any fragment of text inside a PDF document. And finally the View is a wrapper for other elements, imagine this is like a div.

If you are familiar with React Native, the API of React PDF is really similar, this because the library is a custom renderer for React, not just a library of components.

Now, we could create a custom PDF component, the following is the example from their documentation.

// Create styles using StyleSheet.create as in React Native
const styles = StyleSheet.create({
  page: {
    flexDirection: "row",
    backgroundColor: "#E4E4E4",
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
  },
});

// Create a component rendering a Document with a Page and inside any element you want
function MyDocument() {
  return (
    <Document>
      {/* Create a page and set the size to A4, and apply the styles */}
      <Page size="A4" style={styles.page}>
        {/* Create View with some Text inside*/}
        <View style={styles.section}>
          <Text>Section #1</Text>
        </View>
        {/* Create another View with some Text inside*/}
        <View style={styles.section}>
          <Text>Section #2</Text>
        </View>
      </Page>
    </Document>
  );
}

Finally, to render it we can use ReactDOM.render as in any React application.

ReactDOM.render(
  <PDFViewer>
    <MyDocument />
  </PDFViewer>,
  document.querySelector("#root")
);

This will create an iframe with an inline blob for the content of the PDF, so the PDFViewer is the native PDF viewer of the browser the user is using at the moment and not a custom UI.