When working on React projects, one thing I’ve learned is that having the right tools can make or break the user experience. And when it comes to displaying documents, PDFs are still one of the best ways to share content, whether it’s reports, manuals, or e-books. The challenge, though, is how to integrate a reliable PDF viewer into your app without jumping through hoops.
In this article, I’ll walk you through four different ways to build a PDF viewer in React.js. From quick and simple methods like iFrame and opening PDFs in a new tab, to more customizable options like PDF.js and react-pdf—you’ll be able to choose the approach that works best for your project.
Why PDFs Matter in Web Development
Rendering PDFs on websites comes with a wide range of use cases. Here are some scenarios where PDFs can really come in handy:
Financial Reports
Imagine you’re building a finance dashboard, and your users need to access quarterly reports or balance sheets. By embedding these documents as PDFs, users can easily download, print, or view them in high resolution on any device. Plus, you keep the formatting consistent and professional, making sure nothing looks out of place.Sales Invoices
For apps that generate or display invoices, PDFs are the perfect format to ensure clarity and accuracy. You can provide users with downloadable, printable invoices that maintain the exact layout and branding you’ve designed. No more worrying about documents being altered or misinterpreted.Research Papers
If you’re working on a platform that handles academic content or research, PDFs are a great way to present papers, journal articles, and white papers. Researchers can zoom in for detail, highlight key points, or leave annotations—all while preserving the document’s original format.Legal Contracts
For businesses dealing with contracts, confidentiality agreements, or any legal documents, PDFs are essential for maintaining integrity and security. PDFs ensure that legal contracts remain tamper-proof, preserving the original formatting and allowing for secure digital signatures. This is crucial when handling sensitive agreements, ensuring they can be easily shared, viewed, and stored by all parties involved without the risk of edits.
React PDF: A Flexible and Powerful PDF Viewer for React.js
Before diving into the technical side of things, let me introduce you to React PDF—a library I’ve been working on that brings PDF viewing directly into your React or Next.js applications. With over 20 features including theme customization, external APIs, and responsive layouts, it’s perfect for ensuring your users can interact with PDFs without leaving your site.
If you’re interested in trying it out, I’d be super grateful if you could check out React PDF. Your support will motivate me to keep creating more content! ❤️‍🔥
Method 1: Open PDF in a New Tab
If you're working in React and need a simple way to open PDFs, Method 1 is your go-to solution: opening the PDF in a new browser tab. Let's break it down:
1. Add a Link or Button
In your React component, create a link or button to open the PDF.
<a href="/your-pdf.pdf" id="pdfLink" target="_blank">Open PDF</a>
<!-- or button -->
<button id="pdf-button">Open PDF</button>
2. Trigger the PDF
Add an onclick
event to open the PDF in a new tab.
const pdfUrl = '/your-pdf-url-goes-here.pdf';
document.getElementById('pdf-button').onclick = function() {
window.open(pdfUrl, '_blank');
};
Pros and Cons
Pros:
- Easy to Implement: This method is quick and simple.
- Direct Access: Users can view the PDF without anything in between.
Cons:
- Limited Control: You can't fully control how the PDF is displayed.
- Browser Differences: The way it behaves can vary between browsers.
When to Use It
Use this method when you want to keep the PDF viewer separate from your main website. For instance, if embedding it in an iframe isn't ideal.
Method 2: Using an iFrame, Embed, or Object
A simple way to display PDFs in React is by using an <iframe>
, <embed>
, or <object>
element. These methods leverage the browser’s built-in PDF capabilities, allowing you to embed the PDF directly into your app.
How to Implement:
- Create your React project.
- Add one of these elements (
<iframe>
,<embed>
, or<object>
) in your JSX. - Set the
src
attribute to the PDF file’s URL.
<iframe>
Example:
<iframe src="/your-pdf-url.pdf" width="100%" height="600px"></iframe>
<embed>
Example:
<embed src="/your-pdf-url.pdf" width="100%" height="600px" type="application/pdf" />
<object>
Example:
<object data="/your-pdf-url.pdf" width="100%" height="600px" type="application/pdf">
<p>Your browser doesn’t support PDFs. Please download the PDF to view it: <a href="/your-pdf-url.pdf">Download PDF</a>.</p>
</object>
You can see a React code in my Github repository
Pros:
- Super Easy: It’s quick and simple to implement.
- Uses Browser’s PDF Viewer: No extra libraries required—just use the browser’s native PDF viewer.
- No Setup Needed: Works right away without additional configuration.
Cons:
- Limited Control: You can’t control the PDF viewer’s interface or customize it.
- Browser Compatibility: Not all browsers handle these methods the same way.
- Customization Limits: These options don't offer much flexibility for customizing the viewing experience.
When to Use It:
Use these methods when you want a fast, straightforward solution and don’t need to customize the PDF viewer.
Method 3: Using PDF.js
If you need more control over how PDFs are displayed and interacted with, PDF.js is a great option. Created by Mozilla, PDF.js lets you fully customize the PDF viewing experience within your app.
How to Implement:
- Install the PDF.js library in React project.
npm install pdfjs-dist
- Create a React component to render the PDF using PDF.js.
import { PdfProps } from "../types";
import * as PDFJS from "pdfjs-dist";
import type {
PDFDocumentProxy,
RenderParameters,
} from "pdfjs-dist/types/src/display/api";
import { useCallback, useRef, useState, useEffect } from "react";
export default function PdfJs(props: PdfProps) {
PDFJS.GlobalWorkerOptions.workerSrc =
"https://unpkg.com/pdfjs-dist@4.7.76/build/pdf.worker.min.mjs";
const { src } = props;
const canvasRef = useRef<HTMLCanvasElement>(null);
const [pdfDoc, setPdfDoc] = useState<PDFDocumentProxy>();
const [currentPage, setCurrentPage] = useState(1);
let renderTask: PDFJS.RenderTask;
const renderPage = useCallback(
(pageNum: number, pdf = pdfDoc) => {
const canvas = canvasRef.current;
if (!canvas || !pdf) return;
canvas.height = 0;
canvas.width = 0;
// canvas.hidden = true;
pdf
.getPage(pageNum)
.then((page) => {
const viewport = page.getViewport({ scale: 1.5 });
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext: RenderParameters = {
canvasContext: canvas.getContext("2d")!,
viewport: viewport,
};
try {
if (renderTask) {
renderTask.cancel();
}
renderTask = page.render(renderContext);
return renderTask.promise;
} catch (error) {}
})
.catch((error) => console.log(error));
},
[pdfDoc]
);
useEffect(() => {
renderPage(currentPage, pdfDoc);
}, [pdfDoc, currentPage, renderPage]);
useEffect(() => {
const loadingTask = PDFJS.getDocument(src);
loadingTask.promise.then(
(loadedDoc) => {
setPdfDoc(loadedDoc);
},
(error) => {
console.error(error);
}
);
}, [src]);
const nextPage = () =>
pdfDoc && currentPage < pdfDoc.numPages && setCurrentPage(currentPage + 1);
const prevPage = () => currentPage > 1 && setCurrentPage(currentPage - 1);
return (
<div>
<button onClick={prevPage} disabled={currentPage <= 1}>
Previous
</button>
<button
onClick={nextPage}
disabled={currentPage >= (pdfDoc?.numPages ?? -1)}
>
Next
</button>
<canvas ref={canvasRef}></canvas>
</div>
);
}
You can find a complete example code on my Github: components/PdfJs.tsx
.
Here is the result 👇
Pros:
- Advanced Features: PDF.js provides powerful PDF rendering with options like zoom, page navigation, and more.
- Highly Customizable: You have full control over how the PDF is displayed and interacted with.
- Cross-Browser Support: Works across most modern browsers.
- Well-Maintained: Backed by a big community with regular updates.
Cons:
- Learning Curve: It takes time to learn and implement.
- More Complex: Setting it up is harder compared to using iFrame or opening PDFs in a new tab.
- Documentation Challenges: The docs can be tough to follow.
- Integration Issues: Customizing it for frameworks like React, Angular, or Vue can be tricky.
- Higher Complexity: Handling advanced interactions with PDFs increases the complexity.
When to Use It:
Use PDF.js when you need full control over the PDF viewer and want to add advanced features directly into your app’s interface.
Method 4: Using react-pdf (MIT)
react-pdf is an open-source package built on top of PDF.js that makes it easier to display PDFs in React apps while simplifying the development process.
How to Implement:
- Install
react-pdf
using npm or yarn.
npm install react-pdf
- Import the
react-pdf
component into your app.
import { pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
- Follow the instructions on GitHub for detailed setup.
- Create a React component to render PDF
export default function PdfReactPdf({ src }: PdfProps) {
const [numPages, setNumPages] = useState<number>();
const [pageNumber, setPageNumber] = useState<number>(1);
function onDocumentLoadSuccess({ numPages }: { numPages: number }): void {
setNumPages(numPages);
}
function nextPage() {
setPageNumber((v) => ++v);
}
function prevPage() {
setPageNumber((v) => --v);
}
return (
<div style={{ width: "100%", height: "100%" }}>
<button onClick={prevPage} disabled={pageNumber <= 1}>
Previous
</button>
<button onClick={nextPage} disabled={pageNumber >= (numPages ?? -1)}>
Next
</button>
<Document
file={src}
onLoadSuccess={onDocumentLoadSuccess}
className="my-react-pdf"
>
<Page pageNumber={pageNumber} />
</Document>
<p>
Page {pageNumber} of {numPages}
</p>
</div>
);
}
You can check out my example on my Github: components/PdfReactPdf.tsx
.
Pros:
- Easy Integration: Works smoothly with React. Better developer documentation compared to PDF.js.
- More Control: Offers more customization than iFrame or New Tab methods.
- Responsive and Customizable: Adjusts well to different screen sizes and offers some customization.
Cons:
- More Setup: Takes a bit more effort to set up compared to simpler methods.
- Limited Advanced Features: Doesn’t offer as much flexibility as using the full PDF.js library.
When to Use It:
Use react-pdf if you need an easy-to-implement, customizable PDF viewer for your React project.
Conclusion
There are several ways to implement a PDF viewer in React.js. Using iFrame or opening the PDF in a new tab offers simplicity but limits customization. PDF.js provides advanced features and control, but it comes with added complexity. react-pdf (open-source) bridges the gap by offering ease of use with customization options.
Choose the method that best fits your project’s needs, whether it’s speed, simplicity, or control over the user experience.
Is there a Better Solution?
While methods like iFrame or opening PDFs in a new tab can be quick fixes, they don’t offer much control or customization. PDF.js and react-pdf (an open-source library for React) provide more advanced options, but they come with their own challenges—especially if you’re looking for something easier to implement, maintain, and customize for your specific React project.
That’s why I’m building React PDF (not to be confused with react-pdf). While react-pdf is a great open-source library, React PDF is designed to offer more flexibility, powerful customization options, and a simpler setup process tailored to developers working on both small and complex React applications.
Made for React.js: Unlike more general libraries, React PDF is built from the ground up to work seamlessly with React. Whether you need quick rendering or advanced features, it integrates easily into your project with just a few lines of code.
Customization without Complexity: With React PDF, you have full control over the appearance and behavior of your PDF viewer. You can match the viewer’s design to your app’s theme, add interactive features like search and bookmarking, and customize the layout—all without the hassle of dealing with complex configurations.
Extensive Feature Set: Whether you need basic functionality like viewing PDFs or more advanced features like rotation, different scrolling modes, and responsive design, React PDF has you covered. Plus, it’s built with performance in mind, so you don’t have to worry about lag when handling large files.
User-Friendly Documentation: I’ve made sure the technical docs are clear and easy to follow. From starter kits to detailed API references, everything is in place to help you get up and running fast.
Reliable Support and Updates: As developers, I know how important it is to have reliable support. That’s why React PDF comes with responsive customer support and regular updates to keep the library optimized and bug-free.
If this sounds like what you need, I’d be grateful if you could check out React PDF. Your support encourages me to keep improving and building tools for the community. Thank you! 🙏