Introduction to pdfjs-dist in React
As web developers, creating applications that handle PDF documents effectively is a common requirement. Whether you’re building an application that displays invoices, reports, or other important documents, integrating PDF functionalities can enhance the user experience. One of the most popular libraries for handling PDFs in JavaScript is pdf.js, a powerful tool developed by Mozilla. The pdfjs-dist package allows us to easily embed PDF viewing features in our React applications.
In this tutorial, we’ll dive into how to use pdfjs-dist to create a printable PDF viewer in your React app. We’ll cover the necessary setup, how to load and display a PDF document, and finally, how to implement a print feature to let users print their PDFs directly from the browser. Along the way, you’ll learn best practices and tips to ensure a seamless and efficient PDF viewing experience.
This guide is designed for developers with a basic understanding of React and JavaScript. If you’re comfortable with handling components and props but want to enhance your skill set with PDF manipulation, you’re in the right place!
Setting Up Your React Application
Before we dive into the coding part, we need to set up a new React application where we’ll implement the PDF viewer. You can do this with Create React App for its simplicity and ease of use.
npx create-react-app pdf-viewer-app
cd pdf-viewer-app
npm start
Next, we need to install the pdfjs-dist library. Open your terminal in the application directory and run the following command:
npm install pdfjs-dist
After successfully installing the library, we’re ready to start building our PDF viewer component.
Creating the PDFViewer Component
Let’s create a new component called PDFViewer.js in the src directory. This component will be responsible for loading and displaying the PDF documents.
import React, { useEffect, useRef } from 'react';
import { pdfjs } from 'pdfjs-dist';
const PDFViewer = ({ url }) => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const context = canvas.getContext('2d');
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;
const loadPDF = async () => {
const loadingTask = pdfjs.getDocument(url);
const pdf = await loadingTask.promise;
const page = await pdf.getPage(1);
const viewport = page.getViewport({ scale: 1 });
canvas.width = viewport.width;
canvas.height = viewport.height;
const renderContext = {
canvasContext: context,
viewport,
};
await page.render(renderContext).promise;
};
loadPDF();
}, [url]);
return <canvas ref={canvasRef} />;
};
export default PDFViewer;
In this component, we are utilizing useRef to create a reference to our canvas element where the PDF will be rendered. The PDF.js library loads the document from the provided URL, and we render the first page onto the canvas when the component mounts. Make sure to pass the PDF URL as a prop when using the PDFViewer component.
Integrating the PDFViewer Component
Now, let’s modify the App.js file to incorporate our PDFViewer component. Replace the content in App.js with the following:
import React from 'react';
import PDFViewer from './PDFViewer';
const App = () => {
return (
<div>
<h1>PDF Viewer with pdfjs-dist</h1>
<PDFViewer url='https://example.com/sample.pdf' />
</div>
);
};
export default App;
This code imports our newly created PDFViewer component and uses it, passing the URL of a sample PDF document. Ensure that the URL points to a publicly accessible PDF file; otherwise, it will fail to load.
Implementing the Print Feature
Now that we’ve successfully integrated the PDF viewer into our app, let’s add the ability to print the displayed PDF. Printing can be done using the browser’s built-in print function, but we want to ensure users can print the PDF directly from our viewer.
To implement the print functionality, we can add a button below the PDF viewer that, when clicked, will trigger the print dialog. We will modify the App.js file again:
const App = () => {
const printPDF = () => {
const pdfFrame = document.querySelector('canvas');
const printWindow = window.open('', '_blank');
printWindow.document.write(`<html><body><h1>Print PDF</h1><img src='${pdfFrame.toDataURL()}' /></body></html>`);
printWindow.document.close();
printWindow.print();
};
return (
<div>
<h1>PDF Viewer with pdfjs-dist</h1>
<PDFViewer url='https://example.com/sample.pdf' />
<button onClick={printPDF}>Print PDF</button>
</div>
);
};
In the code above, we define a function called printPDF that handles the printing of the canvas content. It opens a new window, writes a simple HTML document into it, and uses the toDataURL() method to get the contents of the canvas as an image. This allows us to print the PDF page displayed in the canvas.
Enhancing User Experience with Loading Indicators
While loading a PDF, it’s good practice to provide feedback to users, indicating that a process is ongoing. We can introduce a loading state to inform users when the PDF is being fetched.
Here’s how you can enhance the PDFViewer component by adding a loading indicator:
const PDFViewer = ({ url }) => {
const canvasRef = useRef(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const loadPDF = async () => {
setIsLoading(true);
const loadingTask = pdfjs.getDocument(url);
const pdf = await loadingTask.promise;
const page = await pdf.getPage(1);
const viewport = page.getViewport({ scale: 1 });
canvas.width = viewport.width;
canvas.height = viewport.height;
const renderContext = {
canvasContext: context,
viewport,
};
await page.render(renderContext).promise;
setIsLoading(false);
};
loadPDF();
}, [url]);
return (
<>
{isLoading ? <p>Loading PDF...</p> : <canvas ref={canvasRef} />}
<>
);
};
Here we’ve added a loading state that starts as true and switches to false once the PDF has finished loading. This gives users immediate feedback that something is happening in the background.
Conclusion
In this tutorial, we explored how to integrate pdfjs-dist into a React application to create a simple yet effective PDF viewer. We learned how to load a PDF document, display it on a canvas, and implement a print functionality that enhances user experience. We also discussed the importance of providing feedback to users during the loading process.
With these skills, you can extend the functionality of your PDF viewer further, incorporating features such as page navigation, zooming, and more. The possibilities are nearly endless, and by leveraging the power of pdf.js, you can deliver high-quality PDF handling capabilities in your web applications.
So go ahead, experiment with your React applications, and start building amazing web experiences with PDF support using pdfjs-dist! Happy coding!