Blog Post

How to Build a React.js PDF Viewer with react-pdf

Illustration: How to Build a React.js PDF Viewer with react-pdf

In this blog post, you will learn how to build a PDF Viewer using React.js and the react-pdf library. React.js is the leading JavaScript library for building user interfaces (UIs). It was created and is maintained by Meta, formerly Facebook. Meta, Instagram, Netflix, Slack, Airbnb, and many other companies use React.js, and it can be used to create a variety of different applications. In this blog post, we’ll use it to create a PDF viewer.

In the first part of this blog post, we’ll look at how to create the PDF viewer with an open source library, and in the second part, we’ll provide a step-by-step guide on how to integrate the PSPDFKit React.js PDF viewer library into a React.js project.

Open Source React.js PDF Viewer Libraries

There are a couple of open source React PDF viewer libraries. One of the most popular is the @react-pdf/renderer library, with 170K weekly downloads on npm. It’s used for creating PDF files in the browser, on the server, or on mobile devices. If you want to work with this library, please refer to our blog post on How to Create a PDF with React.js.

Another popular library is react-pdf by Wojciech Maj, with around 400K weekly downloads on npm. It’s used to display existing PDFs. We’ll look at how to use this library for the purpose of creating a PDF viewer.

react-pdf provides a React component API for opening PDF files and rendering them using PDF.js. PDF.js is an open source JavaScript library for rendering PDF files.

Let’s look at some of this library’s features before creating our project:

  • Ease of use
  • Support for custom events, text selection, and non-Latin characters
  • Multiple rendering methods
  • Cross-browser compatibility
  • Accessibility
  • Free and open source

Requirements to Get Started

To get started, you’ll need:

  • Node.js version 14 or later.

  • 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 create-react-app:

npx create-react-app react-pdf-example

After the project is created, change the directory into the project folder:

cd react-pdf-example

Adding react-pdf

  1. Now, you can install the npm package for the react-pdf library from the terminal:

npm install react-pdf
  1. Place the file you want to render inside the public directory of the react-pdf-example project. You can use our demo document as an example; you just need to rename it to document.pdf.

Displaying a PDF

  1. react-pdf comes with two components: Document and Page. 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, open src/App.js and replace its contents with the following:

import { useState } from 'react';
import { Document, Page } from 'react-pdf/dist/esm/entry.webpack';

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"
				onLoadSuccess={onDocumentLoadSuccess}
			>
				<Page pageNumber={pageNumber} />
			</Document>
		</div>
	);
};

export default App;

For react-pdf to work, PDF.js worker needs to be provided. You can do this in a couple of ways. Since you imported Document and Page from react-pdf/dist/esm/entry.webpack, this will automatically provide the worker for webpack 5. You can read more about how to configure PDF.js worker in your project here.

  1. Now, start the application by running:

npm start

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.

Information

You can access the full code on GitHub.

Overall, react-pdf is a great open source project, but it does have 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 some text in the PDF, you’ll see that it’s not a good user experience.

Building a React.js PDF Viewer with PSPDFKit

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

  1. Use create-react-app to scaffold out a simple React application:

npx create-react-app pspdfkit-react-example
  1. Change to the created project directory:

cd pspdfkit-react-example

Adding PSPDFKit to Your Project

  1. Now, add PSPDFKit for Web as a dependency:

npm install pspdfkit
  1. As you’re using the WebAssembly build of PSPDFKit for Web, the final setup step is to copy files that 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.

  1. Make sure your public directory contains a pspdfkit-lib directory with the PSPDFKit library assets.

Displaying a PDF

  1. Add the PDF document you want to display to the public directory. You can use our demo document as an example.

  2. Add a component wrapper for the PSPDFKit library and save it as components/PdfViewerComponent.js:

import { useEffect, useRef } from 'react';

export default function PdfViewerComponent(props) {
	const containerRef = useRef(null);

	useEffect(() => {
		const container = containerRef.current;
		let PSPDFKit;

		(async function () {
			PSPDFKit = await import('pspdfkit');
			PSPDFKit.load({
				// Container where PSPDFKit should be mounted.
				container,
				// 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}/${process.env.PUBLIC_URL}`,
			});
		})();

		return () => PSPDFKit && PSPDFKit.unload(container);
	}, [props.document]);

	return (
		<div
			ref={containerRef}
			style={{ width: '100%', height: '100vh' }}
		/>
	);
}

To load PSPDFKit for Web into the PdfViewerComponent, use PSPDFKit.load when the component has mounted.

  1. Now, all that’s left is to render the PdfViewerComponent in App.js by loading the PDF you downloaded earlier:

import PdfViewerComponent from './components/PdfViewerComponent';

function App() {
	return (
		<div className="App">
			<div className="App-viewer">
				<PdfViewerComponent document={'document.pdf'} />
			</div>
		</div>
	);
}

export default App;
  1. You can also open a different PDF file by adding a button and adding a handler to the onClick event:

import { useState } from "react";
import PdfViewerComponent from "./components/PdfViewerComponent";

function App() {
  const [document, setDocument] = useState("document.pdf");

  return (
    <div className="App">
      <button
        className="App-button"
        onClick={() => setDocument("another-example.pdf")}
      >
        Open another document
      </button>
      <div className="App-viewer">
        <PdfViewerComponent document={document} />
      </div>
    </div>
  );
}

export default App;

When you click Open another document, it loads the another-example.pdf file.

  1. Your project structure should now look like this:

pspdfkit-react-example
├── public
│   ├── pspdfkit-lib
│   └── document.pdf
│   └── another-example.pdf
├── src
│   ├── components
│   |   └── PdfViewerComponent.js
|   └── App.js
└── package.json
  1. Start the app and run it in your default browser:

npm start

You should now see your PDF rendered in the container element. Try using the toolbar to navigate, annotate, and search the document. Please note that because PSPDFKit is a commercial product, you’ll see a PSPDFKit for Web Evaluation notice on the document. To get a license key, contact sales.

Information

You can find the finished code on GitHub.

If you hit any snags, don’t hesitate to reach out to our support team for help.

Adding Even More Capabilities

Once you’ve deployed your viewer, you can start customizing it to meet your specific requirements or easily add more capabilities. To help you get started, here are some of our most popular React.js guides:

Conclusion

In this post, you first saw how to build a React.js PDF viewer with the react-pdf library. In the second half, you walked through how to deploy the PSPDFKit React.js PDF viewer.

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.

Related Products
Share Post
Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
DESIGN  |  Web • Processor • API • PDF Generation • Tips

Adding Custom Fonts to HTML Documents

DESIGN  |  Web • Processor • API • PDF Generation • Tips

HTML-to-PDF Invoice Generation with Headers and Footers

DEVELOPMENT  |  Web • Products • Support

Scaling Sync Performance: A Customer Story