In this blog post, you’ll learn how to build a React.js PDF viewer using the 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
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 qdvanced PDF reatures — 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 UI controls, you can easily embed PDF documents into your React application using standard HTML tags like <iframe>
, <embed>
, and <object>
. These methods are simple to implement and don’t require additional libraries.
1. 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
✘ Limited customization options
✘ No built-in controls for annotations or text selection
2. Using embed
The <embed>
tag is another way to display a PDF directly in your React app. It’s straightforward and works similarly to <iframe>
.
Example:
function PDFViewer() { return ( <div> <h2>Embedding PDF with embed</h2> <embed src="/document.pdf" type="application/pdf" width="100%" height="1000px" /> </div> ); } export default PDFViewer;
Pros
✔ Simple and lightweight
✔ Good for basic PDF display
Cons
✘ Limited browser support for advanced features
✘ No built-in navigation or annotation tools
3. Using object
The <object>
tag is a more flexible way to embed PDFs. It can also be used to embed other types of media, like images or videos.
Example:
function PDFViewer() { return ( <div> <h2>Embedding PDF with object</h2> <object data="/document.pdf" type="application/pdf" width="100%" height="1000px" > <p> Your browser does not support PDFs.{' '} <a href="/document.pdf">Download the PDF</a>. </p> </object> </div> ); } export default PDFViewer;
Pros
✔ Provides a fallback option for unsupported browsers
✔ More flexible than <iframe>
and <embed>
Cons
✘ Slightly more complex to implement
✘ Limited customization options
Comparison of embedding methods
Method | Ease of use | Customization | Browser support | Fallback option |
---|---|---|---|---|
<iframe> |
Easy | Low | Excellent | No |
<embed> |
Easy | Low | Good | No |
<object> |
Moderate | Moderate | Excellent | Yes |
When to use these methods
These embedding methods are ideal for:
-
Simple PDF display — If you only need to display a PDF without advanced features.
-
Quick prototyping — When you want to test or prototype a feature without installing additional libraries.
-
Lightweight applications — For projects where minimizing dependencies is a priority.
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.
Open source React PDF viewer libraries
For more advanced PDF rendering in React, you can use dedicated libraries. Below are two popular options.
-
Use case — Creating PDFs in React (browser, server, or mobile).
-
Popularity — ~510K weekly downloads on npm.
-
Guide — Check out our how to create a PDF with React.js tutorial.
-
Use case — Displaying existing PDFs in a React app.
-
Popularity — ~950K weekly downloads on npm.
-
Guide — This blog post will walk you through integrating
react-pdf
to build a custom React PDF viewer.
Why choose react-pdf for your React PDF viewer?
react-pdf
is an excellent choice for developers who want to integrate PDF viewing functionality into their React applications. Here are some key benefits:
✅ Ease of integration — react-pdf
offers a simple and straightforward API, making it easy to add PDF viewing capabilities to existing React projects. You can quickly display PDFs with minimal setup.
✅ Flexibility — The library provides components like Document
and Page
, enabling developers to create custom PDF viewers. The Document
component is essential for loading PDF files, and for optimized performance, its recommended to define any configuration options outside the React component using hooks like useMemo
.
✅ Customization — While react-pdf
doesn’t include a built-in UI, this flexibility allows you to create a user interface tailored to your application’s design. You can add navigation controls, zoom functionality, and other features using standard React components.
✅ Compatibility — As a pure React library, react-pdf
is fully compatible with the React ecosystem. Whether you’re using hooks, context, or other React features, react-pdf
integrates seamlessly.
✅ Community support — With around 950K weekly downloads on npm, react-pdf
has a large and active community. This means you can find ample resources, examples, and support from other developers who use the library.
The next section will provide step-by-step instructions on how to build a React PDF viewer with react-pdf
.
Requirements to get started
To get started, you’ll need:
-
A package manager compatible with npm. This guide contains usage examples for Yarn and the npm client (installed with Node.js by default). Make sure the
npm
version is 5.6 or greater.
Building a React.js PDF viewer with react-pdf
Start by creating a React.js project with vite
:
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="pspdfkit-web-demo.pdf" 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(); // Rest of code.
You can read more about how to configure a PDF.js worker in your project here.
-
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.
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.
Building a React PDF viewer with Nutrient
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.
- A prebuilt and polished UI
- 15+ annotation tools
- Support for multiple file types
- Dedicated support from engineers
Creating a new React project
-
Use
vite
to scaffold out a simple React application:
npm create vite@latest pspdfkit-react-example -- --template react
-
Change to the created project directory:
cd pspdfkit-react-example
Adding Nutrient to your project
-
Now, add Nutrient Web SDK as a dependency:
npm install pspdfkit
-
As you’re using the WebAssembly build of Nutrient Web SDK, the final setup step is to copy files the browser will need from the
npm
module:
cp -R ./node_modules/pspdfkit/dist/pspdfkit-lib public/pspdfkit-lib
The code above will copy the pspdfkit-lib
directory from within node_modules/
into the public/
directory to make it available to the SDK at runtime.
-
Make sure your
public
directory contains apspdfkit-lib
directory with the Nutrient library assets.
Displaying a PDF
-
Add the PDF document you want to display to the
public
directory. You can use our demo document as an example. -
Add a component wrapper for the Nutrient library and save it as
src/components/ViewerComponent.jsx
:
import { useEffect, useRef } from 'react'; export default function ViewerComponent(props) { const containerRef = useRef(null); useEffect(() => { const container = containerRef.current; let PSPDFKit; (async function () { PSPDFKit = await import('pspdfkit'); PSPDFKit.unload(container); await PSPDFKit.load({ // Container where PSPDFKit should be mounted. container, // Use dark theme. theme: PSPDFKit.Theme.DARK, // The document to open. document: props.document, // Use the public directory URL as a base URL. PSPDFKit will download its library assets from here. baseUrl: `${window.location.protocol}//${ window.location.host }/${import.meta.env.BASE_URL}`, }); })(); return () => PSPDFKit && PSPDFKit.unload(container); }, [props.document]); return ( <div ref={containerRef} style={{ width: '100%', height: '100vh' }} /> ); }
To load Nutrient Web SDK into the ViewerComponent
, use PSPDFKit.load
when the component has mounted.
-
Now, all that’s left is to render the
ViewerComponent
inApp.jsx
by loading the PDF you downloaded earlier:
import ViewerComponent from './components/ViewerComponent'; function App() { return ( <div className="App" style={{ width: '100vw' }}> <div className="App-viewer"> <ViewerComponent document={'document.pdf'} /> </div> </div> ); } export default App;
-
You can also open a different PDF file by adding a button and adding a handler to the
onClick
event:
// App.jsx import { useState } from 'react'; import ViewerComponent from './components/ViewerComponent'; function App() { const [document, setDocument] = useState('document.pdf'); const handleOpen = () => setDocument('another-example.pdf'); return ( <div className="App" style={{ width: '100vw' }}> <button className="App-button" onClick={handleOpen}> Open another document </button> <div className="App-viewer"> <ViewerComponent document={document} /> </div> </div> ); } export default App;
You can use this example document as a second example. Rename it to another-example.pdf
, and then add it to the /public
folder.
When you click Open another document, it loads the another-example.pdf
file.
-
Your project structure will now look like this:
pspdfkit-react-example ├── public │ ├── pspdfkit-lib │ └── document.pdf │ └── another-example.pdf ├── src │ ├── components │ | └── ViewerComponent.jsx | └── App.js └── package.json
-
Start the app and run it in your default browser:
npm run dev
You’ll now see your PDF rendered in the container
element. Try using the toolbar to navigate through, annotate, and search in the document. 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.
Adding annotations
Now that you have a working React PDF viewer with Nutrient, you can extend its functionality by adding annotation support. Nutrient Web SDK includes built-in annotation tools, allowing users to highlight text, add comments, draw shapes, and more.
Update the ViewerComponent
to include annotation creation. Here’s the updated component code that adds a text annotation to the PDF:
import { useEffect, useRef } from 'react'; export default function ViewerComponent({ document }) { const containerRef = useRef(null); useEffect(() => { const container = containerRef.current; let PSPDFKitInstance; (async function () { const PSPDFKit = await import('pspdfkit'); if (PSPDFKitInstance) PSPDFKit.unload(container); PSPDFKitInstance = await PSPDFKit.load({ container, document, theme: PSPDFKit.Theme.DARK, baseUrl: `${window.location.protocol}//${ window.location.host }/${import.meta.env.BASE_URL}`, }); // Add annotation support. createTextAnnotation(PSPDFKit, PSPDFKitInstance); })(); return () => PSPDFKitInstance && PSPDFKitInstance.unload(container); }, [document]); // Function to add text annotation. async function createTextAnnotation(PSPDFKit, instance) { const annotation = new PSPDFKit.Annotations.TextAnnotation({ pageIndex: 0, text: { format: 'plain', value: 'Welcome to Nutrient PDF Viewer!', }, font: 'Helvetica', isBold: true, horizontalAlign: 'center', boundingBox: new PSPDFKit.Geometry.Rect({ left: 50, top: 200, width: 150, height: 50, }), fontColor: PSPDFKit.Color.BLUE, }); await instance.create(annotation); } return ( <div ref={containerRef} style={{ width: '100%', height: '100vh' }} /> ); }
This will add a text annotation to the first page of the PDF. You can adjust the properties as needed.
Check out React PDF annotations for more information on adding annotations to your React PDF viewer.
If you hit any snags, don’t hesitate to reach out to our Support team for help.
Why Nutrient is the best choice for your React PDF viewer
When it comes to building a robust PDF viewer in React, Nutrient stands out as the top choice. Here’s why:
-
Feature-rich SDK — Nutrient offers a comprehensive set of PDF viewing and editing features, including annotations, digital signatures, form filling, and more.
-
Out-of-the-box UI — Unlike open source alternatives like react-pdf, Nutrient provides a sleek and intuitive user interface, saving development time.
-
Performance optimized — Large PDFs render smoothly, ensuring a seamless experience, even with complex documents.
-
Multiple file format support — Beyond PDFs, Nutrient supports viewing and editing Word, Excel, and image files.
-
Enterprise-grade support — Get dedicated technical support and regular updates to keep your PDF viewer running at its best.
With Nutrient, you get a powerful and scalable solution that lets you deliver the best PDF experience to your users without compromising on performance or usability.
Conclusion
In this blog post, you learned how to build a React.js PDF viewer using the react-pdf
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.
The post explored three methods for embedding PDFs in React applications — <iframe>
, <embed>
, and <object>
— which are easy to implement but come with limitations in customization and interactivity. These are great for simple, quick projects, but if you need more advanced features, Nutrient is the solution.
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 thereact-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.
PDF.js
library to display PDF content.
How do I install and set up react-pdf in a React project?
Installreact-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?
Some limitations ofreact-pdf
include:
- It lacks a built-in user interface for navigation or other controls.
- Text selection can sometimes be inconsistent.
- Users need to manually build features like zoom, search, and navigation controls.
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.