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:
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 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 library. We will cover the following concepts:
To install the react-pdf package, run the following terminal command:
npm i @react-pdf/renderer
The following block of code renders a basic PDF document in the browser:
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:
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 pagesviewer
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 pagePDFViewer
component will render a PDF viewer on the browserLet’s test it out! As the next step, render the BasicDocument
component to the DOM like so:
import BasicDocument from "./BasicDocument"; function App() { return ( <div className="App"> <BasicDocument /> </div> ); } export default App;
We can even reduce the viewer’s available space:
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.
We can display anchor links using the L
component. This is handy for cases where you want to redirect the user to a website:
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.
To attach annotations in your document, use the Note
component. One critical use case for this element is when you need to display comments in a file:
import { Note } from "@react-pdf/renderer"; <Note>This will take the user to Facebook</Note>
Canvas
The 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:
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.
react-pdf also bundles an SVG
component to render SVG diagrams. Just like Canvas
, we can use this for rendering simple diagrams.
This piece of code renders a line on the page:
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
to render a line in the document. Notice that Line
is a child of the Svg
component.
We can also use the Polygon
component to render closed shapes like so:
<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.
The 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:
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.
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:
// 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.
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:
// 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>
With react-pdf, we can render dynamic text using the render
prop of the Text
component like so:
<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.
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:
<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> ) )} />
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!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Leptos is an amazing Rust web frontend framework that makes it easier to build scalable, performant apps with beautiful, declarative UIs.
Learn more about the 5 best JavaScript libraries for dealing with multidimensional arrays, such as ndarray, math.js, and NumJs.
We spoke with Dom about his approach to balancing innovation with handling tech debt and to learn how he stays current with technology.
Vite is a versatile, fast, lightweight build tool with an exceptional DX. Let’s explore when and why you should adopt Vite in your projects.
3 Replies to "Generating PDFs in React with react-pdf"
What is better jsPdf or react-pdf renderer!?
i think React-pdf is better.
and what then? Do I have to generate pdf using browser?