Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 19 #2783

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sharp-fishes-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-pdf/renderer": major
---

Drop support for Internet Explorer and other "dead" browsers
5 changes: 5 additions & 0 deletions .changeset/slimy-suns-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-pdf/renderer": major
---

Add support for and require React 19
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
matrix:
# We aim to test all maintained LTS versions of Node.js as well as the latest stable version
node_version: [18, 20, 21]
react_version: [16, 17, 18]
react_version: [19]

steps:
- name: Checkout
Expand Down Expand Up @@ -111,7 +111,7 @@ jobs:
run: REACT_VERSION=${{ matrix.react_version }} yarn test

e2e-node:
name: Run E2E tests (Node.js ${{ matrix.node_version }}; ${{ matrix.cjs_or_esm == 'cjs' ? 'CJS' : 'ESM' }})
name: "Run E2E tests (Node.js ${{ matrix.node_version }}; ${{ matrix.cjs_or_esm == 'cjs' ? 'CJS' : 'ESM' }})"
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
2 changes: 1 addition & 1 deletion e2e/node-cjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
},
"dependencies": {
"@react-pdf/renderer": "^4.0.0",
"react": "^18.2.0"
"react": "^19.0.0-rc-603e6108-20241029"
}
}
2 changes: 1 addition & 1 deletion e2e/node-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
},
"dependencies": {
"@react-pdf/renderer": "^4.0.0",
"react": "^18.2.0"
"react": "^19.0.0-rc-603e6108-20241029"
}
}
8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,8 @@
"lint-staged": "^10.5.4",
"pdfjs-dist": "3.2.146",
"prettier": "^3.2.0",
"react": "^18.2.0",
"react-16": "npm:react@^16.8.0",
"react-17": "npm:react@^17.0.0",
"react-dom": "^18.2.0",
"react-dom-16": "npm:react-dom@^16.8.0",
"react-dom-17": "npm:react-dom@^17.0.0",
"react": "^19.0.0-rc-603e6108-20241029",
"react-dom": "^19.0.0-rc-603e6108-20241029",
"rimraf": "^2.6.3",
"rollup": "^4.9.0",
"rollup-plugin-copy": "^3.5.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"vite": "^5.0.11"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
"react": "^^19.0.0-rc-603e6108-20241029",
"react-dom": "^^19.0.0-rc-603e6108-20241029"
}
}
8 changes: 3 additions & 5 deletions packages/renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@
"@react-pdf/render": "^4.0.0",
"@react-pdf/types": "^2.7.0",
"events": "^3.3.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"queue": "^6.0.1",
"scheduler": "^0.17.0"
"scheduler": "^0.25.0-rc-603e6108-20241029"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
"react": "^19.0.0"
},
"lint-staged": {
"*.js": [
Expand All @@ -60,7 +58,7 @@
"browserify-zlib": "^0.2.0",
"buffer": "^6.0.3",
"process": "^0.11.10",
"react-reconciler": "0.23.0",
"react-reconciler": "0.31.0-rc-603e6108-20241029",
"size-limit": "^11.0.1",
"util": "^0.12.4"
}
Expand Down
12 changes: 2 additions & 10 deletions packages/renderer/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import nodeResolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import alias from '@rollup/plugin-alias';
import ignore from 'rollup-plugin-ignore';
import terser from '@rollup/plugin-terser';
import commonjs from '@rollup/plugin-commonjs';
Expand All @@ -14,6 +13,7 @@ const nodeInput = './src/node/index.js';
const domInput = './src/dom/index.js';

const babelConfig = () => ({
compact: false,
babelrc: true,
exclude: 'node_modules/**',
babelHelpers: 'runtime',
Expand All @@ -24,21 +24,13 @@ const getExternal = ({ browser }) => [
/@babel\/runtime/,
'react/jsx-runtime',
...(browser ? [] : ['fs', 'path', 'url']),
...Object.keys(pkg.dependencies).filter(
(name) => name !== 'react-reconciler',
),
...Object.keys(pkg.dependencies),
...Object.keys(pkg.peerDependencies),
];

const getPlugins = ({ browser, declarationDests, minify = false }) => [
json(),
...(browser ? [ignore(['fs', 'path', 'url'])] : []),
alias({
entries: {
'react-reconciler':
'react-reconciler/cjs/react-reconciler.production.min.js',
},
}),
babel(babelConfig()),
commonjs({
esmExternals: ['scheduler'],
Expand Down
33 changes: 23 additions & 10 deletions packages/renderer/src/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable import/no-extraneous-dependencies */

import FontStore from '@react-pdf/font';
import renderPDF from '@react-pdf/render';
import PDFDocument from '@react-pdf/pdfkit';
import layoutDocument from '@react-pdf/layout';
import { ConcurrentRoot } from 'react-reconciler/constants';

import createRenderer from './renderer';
import packageJson from '../package.json';

const { version } = packageJson;
import { version } from '../package.json';

const fontStore = new FontStore();

Expand All @@ -23,12 +24,27 @@ const pdf = (initialValue) => {
for (let i = 0; i < listeners.length; i += 1) listeners[i]();
};

const logRecoverableError =
typeof reportError === 'function' ? reportError : console.error;

const container = { type: 'ROOT', document: null };
renderer = renderer || createRenderer({ onChange });
const mountNode = renderer.createContainer(container);
const mountNode = renderer.createContainer(
container,
ConcurrentRoot, // tag
null, // hydration callbacks
false, // isStrictMode
null, // concurrentUpdatesByDefaultOverride
'', // identifierPrefix
logRecoverableError, // onUncaughtError
logRecoverableError, // onCaughtError
logRecoverableError, // onRecoverableError
null, // transitionCallbacks
);

const updateContainer = (doc, callback) => {
renderer.updateContainer(doc, mountNode, null, callback);
renderer.updateContainerSync(doc, mountNode, null, callback);
renderer.flushSyncWork();
};

if (initialValue) updateContainer(initialValue);
Expand Down Expand Up @@ -84,11 +100,8 @@ const pdf = (initialValue) => {

// TODO: rename this method to `toStream` in next major release, because it return stream not a buffer
const toBuffer = async () => {
const {
layout: _INTERNAL__LAYOUT__DATA_,
fileStream,
} = await render();
callOnRender({_INTERNAL__LAYOUT__DATA_});
const { layout: _INTERNAL__LAYOUT__DATA_, fileStream } = await render();
callOnRender({ _INTERNAL__LAYOUT__DATA_ });

return fileStream;
};
Expand Down
46 changes: 31 additions & 15 deletions packages/renderer/src/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
/* eslint-disable no-param-reassign */

import ReactFiberReconciler from 'react-reconciler';
import { DefaultEventPriority } from 'react-reconciler/constants';
import * as scheduler from 'scheduler';

import propsEqual from './utils/propsEqual';

const emptyObject = {};

const appendChild = (parentInstance, child) => {
const appendChild = (parent, child) => {
const isParentText =
parentInstance.type === 'TEXT' ||
parentInstance.type === 'LINK' ||
parentInstance.type === 'TSPAN';
parent.type === 'TEXT' || parent.type === 'LINK' || parent.type === 'TSPAN';
const isChildTextInstance = child.type === 'TEXT_INSTANCE';
const isOrphanTextInstance = isChildTextInstance && !isParentText;

Expand All @@ -26,7 +25,7 @@ const appendChild = (parentInstance, child) => {
return;
}

parentInstance.children.push(child);
parent.children.push(child);
};

const createRenderer = ({ onChange = () => {} }) => {
Expand Down Expand Up @@ -72,10 +71,6 @@ const createRenderer = ({ onChange = () => {} }) => {
// Noop
},

prepareUpdate(element, type, oldProps, newProps) {
return !propsEqual(oldProps, newProps);
},

resetAfterCommit: onChange,

resetTextContent(element) {
Expand All @@ -94,17 +89,17 @@ const createRenderer = ({ onChange = () => {} }) => {
return false;
},

now: Date.now,
noTimeout: -1,

useSyncScheduling: true,

appendChild,

appendChildToContainer(parentInstance, child) {
if (parentInstance.type === 'ROOT') {
parentInstance.document = child;
appendChildToContainer(container, child) {
if (container.type === 'ROOT') {
container.document = child;
} else {
appendChild(parentInstance, child);
appendChild(container, child);
}
},

Expand Down Expand Up @@ -137,11 +132,32 @@ const createRenderer = ({ onChange = () => {} }) => {
textInstance.value = newText;
},

commitUpdate(instance, updatePayload, type, oldProps, newProps) {
commitUpdate(instance, type, oldProps, newProps) {
if (propsEqual(oldProps, newProps)) return;
const { style, ...props } = newProps;
instance.props = props;
instance.style = style;
},

getCurrentUpdatePriority() {
return DefaultEventPriority;
},

setCurrentUpdatePriority() {},

resolveUpdatePriority() {
return DefaultEventPriority;
},

shouldAttemptEagerTransition() {
return false;
},

requestPostPaintCallback() {},

maySuspendCommit() {
return false;
},
});
};

Expand Down
Loading