Show previously rendered PDF instead of showing 'Loading PDF...' #1055
-
Before you start - checklist
DescriptionHi. I built an exact copy of the repl page used by other package, react PDF-renderer. They too use this react-pdf as the pdf viewer. So the issue is whenever user changes some text on the text editor (left side), the PDF preview on the right side disappears for a split second and shows 'Loading PDF..' message. I understand why this happening but it is very annoying for the user to see the PDF flickering each and every time they make some changes on the text editor. So, when the user makes some change on the text editor, is there any way we can 'continue' showing the previously renderered PDF instead of showing the 'Loading PDF..' message while the new PDF is being rendered? More info: Here is how I managed to implement a PDF viewer with pagination using react-pdf, which will display a pdf made using react-pdf/renderer. import { pdfjs, Document, Page, Outline } from 'react-pdf';
import { pdf } from '@react-pdf/renderer';
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
const PDFViewer = ({ children }) => {
const [pdfUrl, setPdfUrl] = useState(null);
const [numPages, setNumPages] = useState(null);
const [pageNumber, setPageNumber] = useState(null);
const onDocumentLoadSuccess = useCallback((document) => {
const { numPages: nextNumPages } = document;
setNumPages(nextNumPages);
setPageNumber(1);
}, []);
const onItemClick = useCallback(
({ pageNumber: nextPageNumber }) => setPageNumber(nextPageNumber),
[],
);
const changePage = useCallback(
(offset) => setPageNumber((prevPageNumber) => (prevPageNumber || 1) + offset),
[],
);
const previousPage = useCallback(() => changePage(-1), [changePage]);
const nextPage = useCallback(() => changePage(1), [changePage]);
useEffect(() => {
const child = React.Children.only(children);
pdf(child).toBlob().then(blob => {
setPdfUrl(URL.createObjectURL(blob));
})
}, [children]);
return (
<Document
file={pdfUrl}
onLoadSuccess={onDocumentLoadSuccess}
onItemClick={onItemClick}
>
<Outline
className="custom-classname-outline"
onItemClick={onItemClick}
/>
<Page renderMode='svg' pageNumber={pageNumber} />
<div className="Test__container__content__controls">
<button
disabled={pageNumber <= 1}
onClick={previousPage}
type="button"
>
Previous
</button>
<span>
{`Page ${pageNumber || (numPages ? 1 : '--')} of ${numPages || '--'}`}
</span>
<button
disabled={pageNumber >= numPages}
onClick={nextPage}
type="button"
>
Next
</button>
</div>
</Document>
);
}
export default PDFViewer; Steps to reproduceDiscussed above Expected behaviorDiscussed above Actual behaviorDiscussed above Additional informationNo response Environment
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hey, https://codesandbox.io/s/react-pdf-prevent-flash-se4r7s Since you didn't provide CodeSandbox so I had no working code to work on, I went ahead and implemented this in react-pdf/renderer's REPL itself here: diegomura/react-pdf-site#91 |
Beta Was this translation helpful? Give feedback.
-
@wojtekmaj I spent today trying to get a similar result by analyzing the react-pdf implementation but without success. Is there any way of exercising greater control over the rendering of the Document? I have a scenario where I need to load pages of a document in parts in small batches due to data modeling, and in large volume. I'm using react-pdf for visualization, react-virtuoso for virtualization and pdf-lib for manipulation. Each document already has metadata with information on the number of pages the document has, so I enter the total number of pages and react-virtuoso calculates the scroll. Then I create a document (ArrayBuffer ) with the blank pages and after each query (ArrayBuffer[]) I merge the new pages with the previously loaded ones and generate a new Blob to pass to the Document. This logic is working very well, but the Document always renders again due to this change, displaying the message Loading, or document not found. I've tried keeping a cache of the rendered document, or some form of memoization, but with these types of immutable data it's not possible. Is there any way to update the file in this stream scenario without re-rendering the document, or even if it does re-render don't make changes to the UI such as messages etc, keeping what was already rendered before the next render? I'm trying not to involve Document on every page, even virtualizing will have a cost. |
Beta Was this translation helpful? Give feedback.
Hey,
A very similar problem already has a solution: show previous
<Page />
when the next one is being rendered. I believe the solution you're looking for will be largely the same, only applied to<Document />
.https://codesandbox.io/s/react-pdf-prevent-flash-se4r7s
Since you didn't provide CodeSandbox so I had no working code to work on, I went ahead and implemented this in react-pdf/renderer's REPL itself here: diegomura/react-pdf-site#91