My component receives a file
object and uses react-pdf
to render it inside a div. The way it’s right now, it only displays the first page, because I have set the value so. Of course, I want to make it so it displays the whole file. This is what I’m trying:
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Document, Page, pdfjs } from "react-pdf"
import { useState, useEffect, useCallback } from "react"
import SimpleBar from "simplebar-react"
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`
interface PaperViewerProps {
file: any
}
function PaperViewer({ file }: PaperViewerProps) {
const [numPages, setNumPages] = useState()
const [pageNumber, setPageNumber] = useState(1)
const [arrayBuffer, setArrayBuffer] = useState<ArrayBuffer | null>(null)
useEffect(() => {
// Ensure file is a valid PDF
if (!file || file.type !== "application/pdf") {
return // Handle invalid file
}
const fileReader = new FileReader()
fileReader.onload = (event) => {
const receivedArrayBuffer = event.target?.result
setArrayBuffer(receivedArrayBuffer as ArrayBuffer)
}
fileReader.readAsArrayBuffer(file)
}, [file])
const onDocumentLoadSuccess = ({ numPages }) => {
setNumPages(numPages)
}
return (
<div>
{arrayBuffer && (
<div className="w-full rounded-md shadow flex flex-col items-center">
<div className="flex-1 w-full max-h-screen">
<SimpleBar autoHide={false} className="max-h-[calc(100vh-10rem)]">
<Document
file={{ data: arrayBuffer }}
className="flex justify-center"
onLoadSuccess={onDocumentLoadSuccess}
>
<Page
pageNumber={pageNumber}
renderTextLayer={false}
renderAnnotationLayer={false}
/>
</Document>
</SimpleBar>
</div>
</div>
)}
</div>
)
}
export default PaperViewer
Here, I am trying to set the total page count in the onDocumentLoadSuccess()
method. However, it throws the following error:
TypeError: Cannot perform Construct on a detached ArrayBuffer
I even tried setting the value manually to a number like so:
const onDocumentLoadSuccess = (2) => {
setNumPages(2)
}
But the error persists. It seems the very act of calling setPageNum
is causing the error. What am I doing wrong here?
I just realized that the error occurs every time there’s a page re-render, i.e., every time a variable is set through a useState
setter. But why? And is there any way to prevent this error while also being able to set state values?
I was running into the same issue when using an ArrayBuffer as the file prop value.
I tried converting the ArrayBuffer to base64string and that worked for me.
First, convert the ArrayBuffer to a base64 string by doing this:
base64String = Buffer.from(arrayBuffer, 'binary').toString('base64')
Then, follow the steps in the react-pdf docs to set the file prop equal to the base64 string:
Hope that helps!