diegomura / react-pdf

📄 Create PDF files using React
https://react-pdf.org
MIT License
14.99k stars 1.19k forks source link

Document React 19 compatability #2964

Open Jussinevavuori opened 4 days ago

Jussinevavuori commented 4 days ago

Is your feature request related to a problem? Please describe. Upgrade documentation on compatability in docs. Add information on React 19 support since 4.1.0.

Describe the solution you'd like Extend documentation on compatibility.

Describe alternatives you've considered None.

Additional context Add information that the React 19 compatibility works by automatically detecting your version based on React.version. This might be especially important for monorepos, see below on why.

I had a difficult issue figuring out why @react-pdf/renderer@^4.1.0 was not working in my monorepo.

How my monorepo looked before

Monorepo root
  /node_modules     <- React 18 installed here
  /apps
    /web            <- React 19 (Next app), depended on @packages/lib
      /node_modules <- React 19 installed here
    /mobile         <- React 18
  /packages
    /lib            <- Depended on @react-pdf/renderer@4.1.4, saw React.version as 18

The issue was caused by version differences. The Next.js app at apps/web had react@19 installed, however it was calling PDF utilities from packages/lib. Due to also having a React Native app in the same repo, I also have react@18 installed in apps/mobile. Version 18 was considered the "default" version and was installed at node_modules/react, where as version 19 was installed into apps/web/node_modules/react. This caused the reconciler to see React.version as 18 and use the wrong reconciler.

I recognized two possible fixes:

  1. Patch the package to force it to use the React 19 reconciler by e.g. replacing const isReact19 = React.version.startsWith('19'); with const isReact19 = true;.
  2. Install React 19 at project root to force it to be considered the "default" version of React.
  3. Enable overriding the version with an environment variable:
    const version = process.env.OVERRIDE_REACT_PDF_RECONCILER_REACT_VERSION || React.version
    const isReact19 = version.startsWith('19');

All solutions may cause their own side-effects, but I decided to go with the third option ultimately after trying out the first two.

Thank you! You have done great work with the React 19 compatability, I appreciate it very much.

Jussinevavuori commented 3 days ago

Update, for anyone struggling with the same React Reconciler issues in a monorepo as I did.

Patching a library didn't produce the wanted results: Initially, I thought that React was only imported by @react-pdf/reconciler/lib/index.js to check the version, however, the reconciler itself also depends on React. The patches described in 1. and 3. will cause react-pdf to apply Reconciler 0.31 for React 19 while importing React 18 (or below). This will -- to my great surprise -- not work.

Instead, installing React 19 at the root of my monorepo (and ensuring all versions were correct) fixed the issue. This works for me, as I know that I will only ever need react-pdf with React 19, no React 18 implementation needs to call react-pdf.