Skip to content

Make Suspense a first class feature #1814

@alexandernanberg

Description

@alexandernanberg

Before you start - checklist

  • I understand that React-PDF does not aim to be a fully-fledged PDF viewer and is only a tool to make one
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions