Generating PDFs in React with react-pdf
Tags: react, webdev, tutorial, programming
Published: 2021-12-16 22:18:14

**Written by [Hussain Arif](https://blog.logrocket.com/author/hussain-arif/)** ✏️

Assume that you own a successful online business. In such a place, you would need to generate invoices and email them to your customers. To create a receipt for each buyer, you would have to do the following:

*   Open your word processor and paste the user’s personal information
*   Write the user’s purchases in a table and calculate the total
*   Download this file and convert it to PDF format
*   Email this document to the user

Sure, that might work. But consider this: what if you get hundreds of customers in a single day? This would waste a lot of time and energy since you’re doing the same process over and over again. So, how do we mitigate this problem?

The best way to solve this issue is to automate this operation by using an API. This is where [react-pdf](https://react-pdf.org/) comes in. It is an open source, easy-to-use library that allows developers to generate PDF documents in a React environment.

In this article, you will learn the basics of the [react-pdf](https://react-pdf.org/) library. We will cover the following concepts:

*   [Simple usage](#simple-usage)
    *   [Fundamental components](#fundamental-components)
    *   [Embedding links](#embedding-links)
    *   [Displaying annotations](#displaying-annotations)
    *   [Displaying graphics in a `Canvas`](#displaying-graphics-in-a-canvas)
    *   [Displaying SVG images](#displaying-svg-images)
    *   [Rendering JPG or PNG photos](#rendering-jpg-or-png-photos)
*   [Advanced concepts](#advanced-concepts)
    *   [Using flex boxes](#using-flex-boxes)
    *   [Page breaks](#page-breaks)
    *   [Dynamic page content](#dynamic-page-content)

## Installation

To install the react-pdf package, run the following terminal command:

```react
npm i @react-pdf/renderer
```

## Simple usage

The following block of code renders a basic PDF document in the browser:

```react
import {
  Document,
  Page,
  Text,
  View,
  StyleSheet,
  PDFViewer,
} from "@react-pdf/renderer";
// Create styles
const styles = StyleSheet.create({
  page: {
    backgroundColor: "#d11fb6",
    color: "white",
  },
  section: {
    margin: 10,
    padding: 10,
  },
  viewer: {
    width: window.innerWidth, //the pdf viewer will take up all of the width and height
    height: window.innerHeight,
  },
});

// Create Document Component
function BasicDocument() {
  return (
    <PDFViewer style={styles.viewer}>
      {/* Start of the document*/}
      <Document>
        {/*render a single page*/}
        <Page size="A4" style={styles.page}>
          <View style={styles.section}>
            <Text>Hello</Text>
          </View>
          <View style={styles.section}>
            <Text>World</Text>
          </View>
        </Page>
      </Document>
    </PDFViewer>
  );
}
export default BasicDocument;
```

A few inferences from this code:

*   The `StyleSheet` module allows developers to apply CSS code on their PDF documents. Here, we are telling React to change the background color and the font color of our pages
*   Furthermore, in the `viewer` object, we are using the `width` and `height` properties. As a result, this will tell react-pdf that we want the browser’s PDF viewer to take up all of the space on the page
*   As the name suggests, the `PDFViewer` component will render a PDF viewer on the browser

Let’s test it out! As the next step, render the `BasicDocument` component to the DOM like so:

```react
import BasicDocument from "./BasicDocument";
function App() {
  return (
    <div className="App">
      <BasicDocument />
    </div>
  );
}
export default App;
```

![Rendering the BasicDocument Component to the DOM](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf.png)

We can even reduce the viewer’s available space:

```react
const styles = StyleSheet.create({
  viewer: {
    width: window.innerWidth / 3,
    height: window.innerHeight / 2,
  },
  //further code...
});
```

In this snippet, we restricted the viewport’s `width` and `height` properties. This will decrease their available size on the page.

![Decreasing the Viewport's Width and Height Properties](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-2.png)

## Fundamental components

### Embedding links

We can display anchor links using the [`L` component](https://react-pdf.org/components#link). This is handy for cases where you want to redirect the user to a website:

```react
import { Link } from "@react-pdf/renderer";
<Text>
  <Link src="www.facebook.com">Go to Facebook</Link>
</Text>
```

Here, we are assigning the `src` prop to Facebook’s website. When the user clicks on this piece of text, the app will redirect them to the page.

![App Redirecting Users to a Different Page](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdf-react-react-pdf-3.gif)

### Displaying annotations

To attach annotations in your document, use the [`Note`](https://react-pdf.org/components#note) component. One critical use case for this element is when you need to display comments in a file:

```react
import { Note } from "@react-pdf/renderer";
<Note>This will take the user to Facebook</Note>
```

![Attaching Annotations Using the Note Component](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdf-react-react-pdf-4.gif)

### Displaying graphics in a `Canvas`

The [`Canvas`](https://react-pdf.org/components#canvas) component lets users draw content on the page. This is suitable for displaying simple diagrams and logos in SVG format.

This code snippet renders a triangle on the page:

```react
import { Canvas } from "@react-pdf/renderer";
// Create styles
const styles = StyleSheet.create({
  canvas: {
    backgroundColor: "black",
    height: 500,
    width: 500,
  },
});
<Canvas
  style={styles.canvas}
  paint={
    (painterObject) =>
      painterObject
        .save()
        .moveTo(100, 100) //move to position 100,100
        .lineTo(300, 100) //draw a line till 300, 100
        .lineTo(300, 300) //draw another line till 300,300
        .fill("red") //when the diagram is drawn, set the background color to pink
  }
/>
```

In the above snippet, we used the `Canvas` component to display a diagram. The `paint` prop is a callback function. One of its parameters is a `painterObject` argument, which gives us access to drawing methods.

![Rendering a Triangle on the Page](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdf-react-react-pdf-5.png)

### Displaying SVG images

react-pdf also bundles an [`SVG` component](https://react-pdf.org/svg) to render [SVG diagrams](https://blog.logrocket.com/how-to-use-svgs-in-react/). Just like `Canvas`, we can use this for rendering simple diagrams.

This piece of code renders a line on the page:

```react
import { Line, Svg } from "@react-pdf/renderer";
// Create styles
const styles = StyleSheet.create({
  line: {
    x1: "0", //starting coords are x1 and y1
    y1: "0",
    x2: "200", //ending coords:
    y2: "200",
    strokeWidth: 2,
    stroke: "rgb(255,255,255)", //stroke color
  },
});
<Svg width={"50%"} height={"50%"} style={{ backgroundColor: "blue" }}>
  <Line style={styles.line} />
</Svg>
```

Here, we used [`Line`](https://react-pdf.org/svg#line) to render a line in the document. Notice that `Line` is a child of the `Svg` component.

![Rendering a Line in the Document](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-6.png)

We can also use the [`Polygon`](https://react-pdf.org/svg#polygon) component to render closed shapes like so:

```react
<Svg width={"50%"} height={"50%"} style={{ backgroundColor: "blue" }}>
  <Polygon
    points="100,100 200,100 200,250 100,250"
    fill="white" //color of background
    stroke="black" //color of border
    strokeWidth={10} //border thickness
  />
</Svg>
```

The `points` prop accepts a dataset of coordinates. This will help the app render the graphic.

![Rendering Closed Shapes in the Document](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-7.png)

### Rendering JPG or PNG photos

The [`Image`](https://react-pdf.org/components#image) component gives us the ability to insert images over the network or on a local disk. This is great for displaying complex diagrams or screenshots.

This block of code renders a 500 by 500 pixel image on the PDF:

```react
import { Image } from "@react-pdf/renderer";
const styles = StyleSheet.create({
  image: {
    width: 500,
    height: 500,
  },
});
<Image
  style={styles.image}
  src="https://image.shutterstock.com/image-photo/tiny-floating-house-on-lake-600w-1980476267.jpg"
/> 
```

The `src` prop contains the source URL of the image that we want to render.

![Rendering a Pixel Image on the PDF](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-8.png)

## Advanced concepts

### Using Flex boxes

Just like CSS, react-pdf lets developers use the `flex` property, which allows for responsive design. This is handy for cases where you want your documents to scale up or down depending on the device’s screen size:

```react
// Create styles. Notice that we have specified a flex direction.
const styles = StyleSheet.create({
  page: {
    flexDirection: "column",
  },
});
<Page size="A4" style={styles.page}>
  <View style={{ backgroundColor: "black", flex: 1 }}></View>
  <View style={(styles.section, { backgroundColor: "pink", flex: 1 })}></View>
</Page>
```

In this piece of code, we used the `flex` property on both of our `View` components. This means that half the page will have a background color of black and the other half will have a pink colored background.

![Using the Flex Property so the Background is Half Black and Half Pink](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-9.png)

### Page breaks

Page breaks are useful for ensuring that a certain element will always show up on the top of the page.

We can enable page breaks via the `break` prop like so:

```react
// Create styles
const styles = StyleSheet.create({
  text: {
    fontSize: 40,
  },
});
// Create Document Component
<Page>
  <Text break style={styles.text}>
    First PDF break
  </Text>
  <Text break style={styles.text}>
    Second break
  </Text>
</Page>
```

![Enabling Page Breaks](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-10.gif)

### Dynamic page content

With react-pdf, we can render dynamic text using the `render` prop of the `Text` component like so:

```react
<Document>
  <Page size="A4">
    <Text
      style={styles.text}
      render={({ pageNumber, totalPages }) =>
        `Page ${pageNumber} of ${totalPages}`
      }
      fixed
    />
  </Page>
  <Page>
    <Text> Hello, second page!</Text>
  </Page>
</Document>
```

Here, the `render` prop has two arguments: `pageNumber` (the current index of the page), and `totalPages` (the total number of pages that this document contains). We are displaying both of their values to the client.

![Displaying Both Page Number and Total Pages to the Client on the Document](https://blog.logrocket.com/wp-content/uploads/2021/12/generating-pdfs-react-react-pdf-11.png)

_N.B., the_ `render` _function is executed twice for_ `<Text />` _elements: once for layout on the page wrapping process, and another one after it knows_ _how many pages the document will have._ _Therefore, use it in cases where app performance is not a problem._

We can also use the `render` prop on our `View` element:

```react
<View render={({ pageNumber }) => (
    //detect if user is NOT on an even page:
        pageNumber % 2 === 0 && (
          <View style={{ background: 'red' }}>
            {/*If condition is fulfilled, display this component*/}
            <Text>I'm only visible in odd pages!</Text>
          </View>
        )
      )} />
```

## Conclusion

In this article, we covered the fundamentals of the react-pdf library. Not only is it secure and robust, but it is also lightweight, thus bringing performance to the table.

Thank you so much for reading! Happy coding!

---

## Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket](https://www2.logrocket.com/react-performance-monitoring). 

[![LogRocket Dashboard Free Trial Banner](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://www2.logrocket.com/react-performance-monitoring)

[LogRocket](https://www2.logrocket.com/react-performance-monitoring) is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — [start monitoring for free](https://www2.logrocket.com/react-performance-monitoring)