How to build a React PDF viewer using react-pdf
react-pdf
library and Nutrient. react-pdf
is a widely used open source library designed for rendering PDF files in React applications, while Nutrient provides a powerful, feature-rich solution for viewing, annotating, and editing PDFs.
Before diving into react-pdf
(opens in a new tab) and Nutrient, you’ll explore native HTML elements like <iframe>
, <embed>
, and <object>
, which allow you to display PDFs in React applications without additional libraries. While these methods are quick and easy to implement, they have limitations in terms of customization and interactivity.
This blog post is structured into three main parts:
- Embedding PDFs using native HTML elements — Learn how to display PDFs with
<iframe>
,<embed>
, and<object>
and compare their pros and cons. - Building a React PDF viewer with
react-pdf
— A step-by-step guide on integratingreact-pdf
into your project to create a fully functional PDF viewer. - Exploring Nutrient for advanced PDF features — Discover how Nutrient extends React’s PDF viewing capabilities with annotations, form filling, and more.
Embedding PDFs in React apps using iframe, embed, and object
If you don’t need advanced features like annotations or custom user interface (UI) controls, the easiest way to embed PDFs in your React app is by using native HTML tags such as <iframe>
, <embed>
, and <object>
. These methods require no additional libraries and are quick to set up — ideal for basic PDF viewing.
Using iframe
The <iframe>
tag is one of the most common ways to embed a PDF in a web application. It allows you to display a PDF document within a frame on your page.
Example:
function PDFViewer() { return ( <div> <h2>Embedding PDF with iframe</h2> <iframe src="/document.pdf" width="100%" height="1000px" title="PDF Viewer" /> </div> );}
export default PDFViewer;
Pros
✔ Easy to implement
✔ Works across all modern browsers
✔ Supports responsive sizing
Cons
✘ No custom navigation or annotations
✘ Limited interactivity (e.g. no built-in text selection or zoom control)
Alternatives: embed and object
While <iframe>
is the most common choice, <embed>
and <object>
offer similar capabilities with slight differences:
<embed>
— Slightly more lightweight than<iframe>
, but lacks fallback support for older browsers.<object>
— Offers better fallback handling (e.g. showing a download link if PDF rendering fails), and can embed other media types too, but is a bit more complex to implement.
You can explore sample implementations for these tags here.
Comparison of embedding methods
Method | Ease of use | Customization | Fallback support | Browser compatibility |
---|---|---|---|---|
<iframe> | ⭐⭐⭐⭐ | ⭐ | ❌ | ✅ Excellent |
<embed> | ⭐⭐⭐⭐ | ⭐ | ❌ | ✅ Good |
<object> | ⭐⭐⭐ | ⭐⭐ | ✅ | ✅ Excellent |
When to use these methods
Use native HTML embedding methods when:
- You just need to display PDFs — no navigation, search, or interactivity required.
- You want a quick prototype without installing extra libraries.
- You’re building a lightweight application that minimizes dependencies.
However, these options fall short for projects needing advanced PDF controls, annotations, or a custom UI. For those, libraries like react-pdf
or commercial SDKs like Nutrient offer much more flexibility and power.
Limitations of embedding PDFs
While these methods are simple, they come with limitations:
- No custom UI — You can’t easily add custom navigation controls, annotations, or search functionality.
- Limited interactivity — Users can’t interact with a PDF beyond basic viewing.
- Performance issues — Large PDFs may load slowly or cause performance issues in the browser.
For more advanced PDF rendering in React, you can use dedicated libraries like react-pdf
or Nutrient.
Comparing React PDF libraries: react-pdf vs @react-pdf/renderer
When choosing a PDF library for your React app, two popular open source options stand out.
@react-pdf/renderer
@react-pdf/renderer(opens in a new tab):
- Use case — Generating PDFs dynamically from React components (e.g. invoices, reports).
- Downloads — ~510K weekly downloads on npm.
- Guide — Check out our how to create a PDF with React.js tutorial.
react-pdf
react-pdf(opens in a new tab):
- Use case — Displaying existing PDFs within React applications.
- Downloads — ~950K weekly downloads on npm.
- Why use it?
- Easy integration with React projects
- Fully customizable UI using
Document
andPage
components - Compatible with hooks and context
- Backed by an active developer community
Keep in mind: You’ll need to build the user interface from scratch and handle performance optimizations for large documents.
The next section covers prerequisites for setting up your PDF viewer.
Requirements to get started
To get started, you’ll need:
- Node.js version 14 or later(opens in a new tab).
- A package manager compatible with npm. This guide contains usage examples for Yarn(opens in a new tab) and the npm(opens in a new tab) client (installed with Node.js by default). Make sure the
npm
version is 5.6 or greater.
You’ll also use Vite(opens in a new tab) to quickly scaffold your React project.
Building a React.js PDF viewer with react-pdf
Start by creating a React.js project with vite
(opens in a new tab):
npm create vite@latest react-pdf-demo -- --template react
After the project is created, change the directory into the project folder:
cd react-pdf-demo
Adding react-pdf
- Now, you can install the npm package for the
react-pdf
library from the terminal:
npm install react-pdf
- Place the file you want to render inside the
public
directory of thereact-pdf-example
project. You can use our demo document as an example; you just need to rename it todocument.pdf
.
Displaying a PDF
react-pdf
comes with two components:Document
andPage
.Document
is used to open a PDF and is mandatory. Within the document, you can mount pages, which are used to render the PDF page. To integrate this into your example project, opensrc/App.jsx
and replace its contents with the following:
import { useState } from 'react';import { Document, Page } from 'react-pdf';
// Text layer for React-PDF.import 'react-pdf/dist/Page/TextLayer.css';
const App = () => { const [numPages, setNumPages] = useState(null); const [pageNumber, setPageNumber] = useState(1);
const onDocumentLoadSuccess = ({ numPages }) => { setNumPages(numPages); };
const goToPrevPage = () => setPageNumber(pageNumber - 1 <= 1 ? 1 : pageNumber - 1);
const goToNextPage = () => setPageNumber( pageNumber + 1 >= numPages ? numPages : pageNumber + 1, );
return ( <div> <nav> <button onClick={goToPrevPage}>Prev</button> <button onClick={goToNextPage}>Next</button> <p> Page {pageNumber} of {numPages} </p> </nav>
<Document file="document.pdf" // Path to your PDF file. onLoadSuccess={onDocumentLoadSuccess} > <Page pageNumber={pageNumber} /> </Document> </div> );};
export default App;
For react-pdf
to work, a PDF.js worker needs to be provided. You can do this in a couple of ways. For most cases, importing the worker will work, as was done in the src/App.jsx
file:
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url,).toString();// The rest of the code.
You can read more about how to configure a PDF.js worker in your project here(opens in a new tab).
- Now, start the application by running the following:
npm run dev
One of the disadvantages of using react-pdf
is that it doesn’t come with a UI. In this example, you’ve rendered two buttons to navigate between pages and showed the total number of pages.
You can access the full code on GitHub(opens in a new tab).
Limitations of react-pdf
Overall, react-pdf
is a great open source project, but it has some disadvantages:
- It doesn’t come with a user interface out of the box. If you need a UI to help users navigate through a PDF, you’ll need to build it from scratch.
- Text selection doesn’t work properly. If you try to select text in a PDF, you’ll see that it’s not a good user experience.
- Rendering large PDF files or documents with many pages can sometimes impact performance, particularly in resource-constrained environments.
Setting up Nutrient Web SDK in a React + Vite project
We offer a commercial React.js PDF library that can easily be integrated into your web application. It comes with 30+ features that let you view, annotate, edit, and sign documents directly in your browser. Out of the box, it has a polished and flexible UI that you can extend or simplify based on your unique use case.
Creating a new React project
Use vite
(opens in a new tab) to scaffold out a simple React application:
npm create vite@latest nutrient-react-example -- --template reactcd nutrient-react-example
Install Nutrient Web SDK
Next, install the @nutrient-sdk/viewer
package:
npm i @nutrient-sdk/viewer
pnpm add @nutrient-sdk/viewer
yarn add @nutrient-sdk/viewer
Copying SDK assets to the public directory
Nutrient Web SDK loads its WebAssembly and supporting files from a local path, so you need to copy them to the public folder. Start by installing the required copy plugin:
npm install -D rollup-plugin-copy
Then, update your Vite config (vite.config.ts
) to copy the SDK’s asset files during build:
import { defineConfig } from 'vite';import react from '@vitejs/plugin-react';import copy from 'rollup-plugin-copy';
export default defineConfig({ plugins: [ copy({ targets: [ { src: 'node_modules/@nutrient-sdk/viewer/dist/nutrient-viewer-lib', dest: 'public/', }, ], hook: 'buildStart', }), react(), ],});
Displaying a PDF
Now that everything is set up, you’ll render a PDF using the Nutrient SDK.
Basic usage in App.tsx
:
import { useEffect, useRef } from 'react';
function App() { const containerRef = useRef(null);
useEffect(() => { const container = containerRef.current; let cleanup = () => {};
(async () => { const NutrientViewer = (await import('@nutrient-sdk/viewer')) .default;
// Unload any previous instance. NutrientViewer.unload(container);
if (container && NutrientViewer) { NutrientViewer.load({ container, document: 'https://www.nutrient.io/downloads/pspdfkit-web-demo.pdf', baseUrl: `${window.location.protocol}//${ window.location.host }/${import.meta.env.PUBLIC_URL ?? ''}`, }); }
cleanup = () => { NutrientViewer.unload(container); }; })();
return cleanup; }, []);
return ( <div ref={containerRef} style={{ height: '100vh', width: '100vw' }} /> );}
export default App;
You can also render a different file by changing the document
path or making it dynamic.
Once everything is configured, start your app:
npm run dev
You’ll now see the Nutrient Web SDK UI rendering your PDF inside the browser!
Note that because Nutrient is a commercial product, you’ll see a Nutrient Web SDK evaluation notice on the document. To get a license key, contact Sales.
You can find the finished code on GitHub(opens in a new tab).
Why Nutrient is the best choice for your React PDF viewer
When it comes to building a production-ready PDF viewer in React, Nutrient stands out with its powerful feature set and ease of use:
✅ Out-of-the-box UI — A polished, responsive interface with built-in toolbars, navigation, zoom, and layout options.
✅ 15+ annotation tools — Highlight text, draw shapes, add comments, and more with zero configuration.
✅ Document editing — Modify text, add pages, redact content, and fill forms directly in the browser.
✅ Broad file support — View and edit PDFs, Word, Excel, and image formats like JPG and PNG.
✅ Optimized performance — Fast rendering even for large, multi-page documents.
✅ Commercial-grade reliability — Backed by dedicated technical support and frequent updates.
If you’re looking for an all-in-one PDF solution with advanced capabilities, Nutrient lets you deliver a rich document experience without building everything from scratch.
Comparing react-pdf and Nutrient SDK
Here’s a quick side-by-side comparison to help you decide which solution fits your needs best:
Feature | react-pdf | Nutrient SDK |
---|---|---|
Out-of-the-box UI | ❌ No | ✅ Yes — prebuilt, customizable |
Annotation tools | ❌ Manual implementation | ✅ 15+ built-in tools |
Form filling | ❌ Not supported | ✅ Fully supported |
Text selection | ❌ Limited and inconsistent | ✅ Optimized for precision and usability |
File format support | PDF only | PDF, DOCX, XLSX, JPG, PNG, etc. |
Licensing | MIT License | Commercial license required |
Performance on large files | May lag | Optimized rendering with WebAssembly |
Accessibility considerations
When choosing how to embed or render PDFs in your React app, it’s important to consider accessibility:
<iframe>
,<embed>
,<object>
— Minimal accessibility support. PDFs embedded this way are often not accessible to screen readers or keyboard users.react-pdf
— Basic ARIA and keyboard navigation can be added manually, but text layers are often inaccessible out of the box.- Nutrient SDK: —Offers better support for accessible navigation, keyboard interaction, and screen reader compatibility. Text layers, tab focus, and annotations are optimized for accessibility out of the box.
For accessibility compliance (e.g. WCAG or Section 508), Nutrient is the more robust solution.
Conclusion
In this blog post, you learned how to build a React.js PDF viewer using the react-pdf
(opens in a new tab) library and Nutrient. While react-pdf
offers a basic PDF viewing solution, Nutrient provides a more powerful, feature-rich alternative for not just viewing PDFs, but also annotating, editing, and signing documents, all with a polished UI.
You can also deploy our vanilla JavaScript PDF viewer or use one of our many web framework deployment options like Vue.js, Angular, and jQuery. To see a list of all web frameworks, start your free trial. Or, launch our demo to see our viewer in action.
FAQ
How can I create a PDF viewer in React.js using react-pdf?
You can create a PDF viewer in React.js by installing the react-pdf
library, importing its components, and using the Document
and Page
components to render PDF files.
What are the main components of the react-pdf library?
The main components are:
Document
— Used for loading the PDF file.Page
— Used for rendering individual pages of the PDF.These components leverage the
PDF.js
library to display PDF content.
How do I install and set up react-pdf in a React project?
Install react-pdf
using npm with the following command: npm install @react-pdf-viewer/react-pdf
Then, set up your project by:
- Importing the necessary components from the library.
- Configuring the
PDF.js
worker file to ensure proper rendering. - Using the
Document
andPage
components to display your PDF.
What are the limitations of the react-pdf library?
react-pdf
doesn’t include built-in UI components and may have limitations with text selection or performance on large files. Read the full list of limitations.
How can I enhance the functionality of a React.js PDF viewer?
You can enhance the functionality by:
- Building custom UI controls such as navigation, zoom, and search functionality.
- Integrating libraries like
Nutrient
to add advanced features like annotations, form filling, and enhanced user interface components.