How to create PDF in React JS Next JS Vite Js
In my current project, I need my application to make PDF files from data, such as reports or certificates. I'm using a popular library called pdf-renderer in my React app to easily generate and download PDF documents. This helps me achieve my project's goal with minimal effort.
Getting started
To get started with react-pdf install the package from the command line,
yarn add @react-pdf/renderer or npm install @react-pdf/renderer or pnpm install @react-pdf/renderer
The basic thing to render a pdf is knowing these important components that pdf-render provides us.
Document
: It is the root of the PDF, like a<html>
tag.Page
: This component represents a single page inside our documents, but we can use multiple inside theDocument
Text
: This component for displaying text, supports nesting of links or other textsView
: The most fundamental component for building a UI, is the design to be nested inside other views, which you can use as a<div>
tag.Image
: A component that can be used for displaying images, keep in mind that you should not miss out on the source object.
Rendering your first PDF on DOM
import { PDFViewer } from '@react-pdf/renderer'; import MyDocument from './MyDocument' const App = () => ( <PDFViewer width={1200} height={1200} showToolbar={false}> <MyDocument /> </PDFViewer> ); export default App
Get the Complete Invoice Code in React JS
import { Document, Page, Text, View, StyleSheet, Font } from '@react-pdf/renderer'; const borderColor = '#000' Font.register({ family: 'Oswald', src: 'https://fonts.gstatic.com/s/oswald/v13/Y_TKV6o8WovbUd3m_X9aAA.ttf', fontWeight: 700 }); const styles = StyleSheet.create({ page: { flexDirection: 'row', // backgroundColor: '#f6fbff', // height: 1000, // width: 1200, padding:20, }, container:{ borderWidth: 2, borderColor: borderColor, }, invoice: { width: 600, marginTop: 5, display: 'flex', fontSize: 10, flexDirection: 'row', justifyContent: 'space-around', }, title: { marginTop: 10, display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'column', fontFamily: 'Times-Roman' }, busenessName: { marginBottom: 5, textAlign: 'center', fontSize: 26, }, businessAddress: { fontSize: 12, marginBottom: 10 }, customerInfo: { borderTopWidth: 2, borderBottomWidth: 2, display: 'flex', justifyContent: 'space-between', flexDirection: 'row', flexWrap: 'wrap', fontSize: 11, fontWeight: 'bold' }, name: { margin: 3 }, basicInfo: { padding: 5, }, invoiceNo: { borderLeftWidth: 2, padding: 5, }, billContanier: { flexDirection: 'row', alignItems: 'start', textAlign: 'start', }, billadd:{ width: '65%', borderRightColor: borderColor, borderRightWidth: 2, borderTopWidth: 2, fontSize: 11, textAlign: 'justify', fontWeight: 'heavy', padding: 4, }, shippAdd: { borderTopWidth: 2, borderRightColor: borderColor, width: '35%', fontSize: 11, textAlign: 'justify', padding: 4, }, itemContainer: { display: 'flex', flexDirection: 'row', borderBottomWidth: 2 }, sNo: { width: '10%', borderRightColor: borderColor, borderTopWidth: 2, fontSize: 12, textAlign: 'justify', fontWeight: 'heavy', padding: 4, }, itemName: { width: '70%', borderRightColor: borderColor, borderRightWidth: 2, borderTopWidth: 2, borderLeftWidth: 2, fontSize: 12, textAlign: 'center', padding: 4, }, itemPrice: { width: '20%', borderRightColor: borderColor, borderTopWidth: 2, fontSize: 12, textAlign: 'center', fontWeight: 'heavy', padding: 4, }, items: { display: 'flex', flexDirection: 'row', alignItems: 'center' }, sNodynamic: { width: '10%', borderRightColor: borderColor, fontSize: 11, textAlign: 'center', fontWeight: 'heavy', padding: 2, }, itemNamedynamic: { width: '70%', borderRightColor: borderColor, borderRightWidth: 2, borderLeftWidth: 2, fontSize: 11, textAlign: 'justify', padding: 4, }, itemPricedynamic: { width: '20%', borderRightColor: borderColor, fontSize: 11, textAlign: 'center', fontWeight: 'heavy', padding: 2, }, termsContanier: { display: 'flex', flexDirection: 'row', borderTopWidth: 2, borderBottomWidth: 2, alignItems: 'center' }, termsRow: { width: '65%', // borderRightColor: borderColor, borderRightWidth: 2, fontSize: 11, textAlign: 'justify', padding: 4, }, priceRow: { width: '35%', fontSize: 11, textAlign: 'justify', }, subtotal: { display: 'flex', flexDirection: 'row', alignItems: 'start', textAlign: 'start', }, gstMgmt: { width: '43%', borderRightColor: borderColor, borderRightWidth: 2, fontSize: 11, textAlign: 'center', fontWeight: 'heavy', }, priceMgmt: { borderRightColor: borderColor, width: '57%', fontSize: 11, textAlign: 'center', }, bordrerdesign:{ borderBottomWidth:2, padding:8 }, paddingdesign:{ padding:2 }, termHeading: { marginTop: 50, marginBottom: 50, marginLeft:20, display: 'flex', justifyContent: 'center', flexDirection: 'column', }, footer: { height: 20, textAlign: 'center', justifyContent:'center', marginLeft:20 }, termCondition: { flexDirection: "row", alignItems: "center", minHeight: 24, height: "auto", fontStyle: "bold", fontSize:12, flexWrap: "wrap", marginTop: 1, }, }); const MyDocument = () => ( <Document> <Page size="A4" style={styles.page}> <View style={styles.container}> <View style={styles.invoice}> <View> <Text>GSTIN:09BBMPG0319L2ZI</Text></View> <View> <Text>TAX INVOICE</Text></View> <View> <Text>Mob:+91-8188088875</Text> <Text style={styles.name}>INVOICE No.: 20</Text> </View> </View> <View style={styles.title}> <Text style={styles.busenessName}>Yagya Event</Text> <Text style={styles.businessAddress}>Business Address:Gomati Nagar, Lucknow</Text> </View> <View style={styles.billContanier}> <Text style={styles.billadd}>Bill To</Text> <Text style={styles.shippAdd}>Shipp To</Text> </View> <View style={styles.billContanier} > <View style={styles.billadd} > <Text style={styles.name}>Name: Mr. Aniruddh Varshney</Text> <Text style={styles.name}>Address : Gomati Nagar, Lucknow </Text> <Text style={styles.name}>GST no.: 09AAICT1512H1ZG</Text> <Text style={styles.name}>Mobile No.: +91 9023606749</Text> </View> <View style={styles.shippAdd}> <Text style={styles.name}>Shipping Address:Delhi</Text> <Text style={styles.name}>Delivery Date:06-01-2024</Text> <Text style={styles.name}>Invoice Date.: 06-01-2024</Text> </View> </View> <View style={styles.itemContainer}> <Text style={styles.sNo}>S.No</Text> <Text style={styles.itemName}>Title</Text> <Text style={styles.itemPrice}>Price</Text> </View> <View style={styles.row}> <View style={styles.items}> <Text style={styles.sNodynamic}>01</Text> <View style={styles.itemNamedynamic}> <Text>Lenovo Thinkpad</Text> <Text>All disputes subject to lucknow jurisdiction</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> <View style={styles.items}> <Text style={styles.sNodynamic}>01</Text> <View style={styles.itemNamedynamic}> <Text>Lenovo Thinkpad</Text> <Text>All disputes subject to lucknow jurisdiction</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> <View style={styles.items}> <Text style={styles.sNodynamic}>01</Text> <View style={styles.itemNamedynamic}> <Text>Lenovo Thinkpad</Text> <Text>All disputes subject to lucknow jurisdiction</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> <View style={styles.items}> <Text style={styles.sNodynamic}>01</Text> <View style={styles.itemNamedynamic}> <Text>Lenovo Thinkpad</Text> <Text>All disputes subject to lucknow jurisdiction</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> <View style={styles.items}> <Text style={styles.sNodynamic}>02</Text> <View style={styles.itemNamedynamic}> <Text>Lenovo Thinkpad</Text> <Text>AMD, 12 GB Ram, 128 SSD</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> <View style={styles.items}> <Text style={styles.sNodynamic}>03</Text> <View style={styles.itemNamedynamic}> <Text>Boat SmartWatch</Text> <Text>4h battery backup, social media</Text> </View> <Text style={styles.itemPricedynamic}>85678</Text> </View> </View> <View style={styles.termsContanier}> <View style={styles.termsRow}> <View> <Text style={styles.paddingdesign}>Bank Details:</Text> <Text style={styles.paddingdesign}>Bank Name : BANDHAN BANK</Text> <Text style={styles.paddingdesign}>Branch : GOMTINAGAR,LUCKNOW</Text> <Text style={styles.paddingdesign}>Account No : 10210009229916</Text> <Text style={styles.paddingdesign}>Bank IFSC : BDBL0001908</Text> <Text style={styles.paddingdesign}>Bank IFSC : BDBL0001908</Text> </View> </View> <View style={styles.priceRow}> <View style={styles.subtotal}> <View style={styles.gstMgmt}> <Text style={styles.bordrerdesign}>SubTotal</Text> <Text style={styles.bordrerdesign}>CGST</Text> <Text style={styles.bordrerdesign}>SGST</Text> <Text style={styles.paddingdesign}>Total</Text> </View> <View style={styles.priceMgmt}> <Text style={styles.bordrerdesign}>180000</Text> <Text style={styles.bordrerdesign}>600</Text> <Text style={styles.bordrerdesign}>600</Text> <Text style={styles.paddingdesign}>20000/-</Text> </View> </View> </View> </View> <View style={styles.termHeading}> <Text>Terms & Conditions</Text> </View> <View style={styles.footer}> <View style={styles.termCondition}> <Text>All amounts are in INR. Please make payments in the specified currency</Text> </View> <View style={styles.termCondition}> <Text style={styles.termCondition}>We accept payments via UPI, Cash, Net Banking, Debit Card</Text> </View> <View style={styles.termCondition}> <Text >Cancellations must be requested in writing within 7 days of the invoice date. Refunds will be issued </Text> </View> <View style={styles.termCondition}> <Text>All amounts are in INR. Please make payments in the specified currency</Text> </View> </View> </View> </Page> </Document> ); export default MyDocument
If I have to point out there is styling limitations for example there is overflow
provides only hidden
property and other do not support, display
only supports flex
and none
.