react-pdf icon indicating copy to clipboard operation
react-pdf copied to clipboard

Make Suspense a first class feature

Open alexandernanberg opened this issue 1 month ago • 1 comments

Before you start - checklist

  • [X] I understand that React-PDF does not aim to be a fully-fledged PDF viewer and is only a tool to make one
  • [X] I have checked if this feature request is not already reported

Description

Today it cumbersome to orchestrate loading states, e.g. when rendering only a single page I want the loader to show the same for both the <Document> and <Page>, I can pass the same element to both loader props, but often that causes the spinner to get out of sync.

The same issue applies to when lazy loading the module, if you want the same loading UI.

Proposed solution

Fully integrate Suspense into the library. Remove all props related to loading or error states and use Suspense and Error boundaries.

Example how this would look

<Suspense fallback="Loading...">
  <Document file={src}>
    {Array.from(new Array(numPages), (_, index) => (
      <Page key={`page_${index + 1}`} pageNumber={index + 1} />
    ))}
  </Document>
</Suspense>

Want separate loading states for each page? Just wrap each page with a suspense boundary

<Suspense fallback="Loading...">
  <Document file={src}>
    {Array.from(new Array(numPages), (_, index) => (
      <Suspense fallback="Loading page...">
        <Page key={`page_${index + 1}`} pageNumber={index + 1} />
      </Suspense>
    ))}
  </Document>
</Suspense>

This also provides more control of the UX when navigating between pages. E.g. to load the next page before navigating, just wrap setPageNumber with a transition.

startTransition(() => {
  setPageNumber((i) => i + 1);
});

Alternatives

N/A

Additional information

Fully integrating Suspense would be a breaking change and likely require React 19 and above.

alexandernanberg avatar Jun 03 '24 07:06 alexandernanberg