diff --git a/.changeset/old-hornets-knock.md b/.changeset/old-hornets-knock.md new file mode 100644 index 00000000..5346436e --- /dev/null +++ b/.changeset/old-hornets-knock.md @@ -0,0 +1,5 @@ +--- +'@hono/react-renderer': major +--- + +feat: use React v19 and specify `react-dom/server.edge` for `renderToReadableStream` diff --git a/package.json b/package.json index 36924d1c..dae4347f 100644 --- a/package.json +++ b/package.json @@ -45,4 +45,4 @@ "vitest": "^3.0.8" }, "packageManager": "yarn@4.0.2" -} \ No newline at end of file +} diff --git a/packages/node-ws/package.json b/packages/node-ws/package.json index c925f215..9c03134b 100644 --- a/packages/node-ws/package.json +++ b/packages/node-ws/package.json @@ -57,4 +57,4 @@ "engines": { "node": ">=18.14.1" } -} \ No newline at end of file +} diff --git a/packages/react-renderer/package.json b/packages/react-renderer/package.json index df392532..45825e8d 100644 --- a/packages/react-renderer/package.json +++ b/packages/react-renderer/package.json @@ -40,17 +40,17 @@ "homepage": "https://github.com/honojs/middleware", "peerDependencies": { "hono": "*", - "react": "*", - "react-dom": "*" + "react": "^19.0.0", + "react-dom": "^19.0.0" }, "devDependencies": { "@arethetypeswrong/cli": "^0.17.4", "@cloudflare/vitest-pool-workers": "^0.7.8", - "@types/react": "^18", - "@types/react-dom": "^18.2.17", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.2", "publint": "^0.3.9", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "tsup": "^8.4.0", "typescript": "^5.8.2", "vitest": "^3.0.8" diff --git a/packages/react-renderer/src/react-renderer.test.tsx b/packages/react-renderer/src/react-renderer.test.tsx index bafa7768..88f6dd27 100644 --- a/packages/react-renderer/src/react-renderer.test.tsx +++ b/packages/react-renderer/src/react-renderer.test.tsx @@ -128,6 +128,7 @@ describe('Basic', () => { ({ children }) => { return ( + {children} ) @@ -139,7 +140,9 @@ describe('Basic', () => { const res = await app.request('/') expect(res).not.toBeNull() expect(res.status).toBe(200) - expect(await res.text()).toBe('

Hello

') + expect(await res.text()).toBe( + '

Hello

' + ) }) it('Should return a content without a doctype', async () => { @@ -161,7 +164,7 @@ describe('Basic', () => { const res = await app.request('/') expect(res).not.toBeNull() expect(res.status).toBe(200) - expect(await res.text()).toBe('

Hello

') + expect(await res.text()).toBe('

Hello

') }) it('Should return a custom doctype', async () => { @@ -187,7 +190,7 @@ describe('Basic', () => { expect(res).not.toBeNull() expect(res.status).toBe(200) expect(await res.text()).toBe( - '

Hello

' + '

Hello

' ) }) @@ -231,6 +234,8 @@ describe('Streaming', () => { expect(res.status).toBe(200) expect(res.headers.get('Transfer-Encoding')).toBe('chunked') expect(res.headers.get('Content-Type')).toBe('text/html; charset=UTF-8') - expect(await res.text()).toBe('

Hello

') + expect(await res.text()).toBe( + '

Hello

' + ) }) }) diff --git a/packages/react-renderer/src/react-renderer.ts b/packages/react-renderer/src/react-renderer.ts index 0a9943b4..5b5b4135 100644 --- a/packages/react-renderer/src/react-renderer.ts +++ b/packages/react-renderer/src/react-renderer.ts @@ -30,10 +30,11 @@ const createRenderer = options?: RendererOptions ) => async (children: React.ReactElement, props?: Props) => { - const node = component ? component({ children, Layout, c, ...props }) : children + const node = component ? await component({ children, Layout, c, ...props }) : children if (options?.stream) { - const { renderToReadableStream } = await import('react-dom/server') + // @ts-expect-error `react-dom/server.edge` is not typed well + const { renderToReadableStream } = await import('react-dom/server.edge') const stream = await renderToReadableStream( React.createElement(RequestContext.Provider, { value: c }, node), options.readableStreamOptions @@ -52,8 +53,8 @@ const createRenderer = typeof options?.docType === 'string' ? options.docType : options?.docType === false - ? '' - : '' + ? '' + : '' const body = docType + renderToString(React.createElement(RequestContext.Provider, { value: c }, node)) return c.html(body) @@ -71,7 +72,7 @@ export const reactRenderer = ( if (component) { // eslint-disable-next-line @typescript-eslint/no-explicit-any c.setLayout((props: any) => { - return component({ ...props, Layout, c }, c) + return component({ ...props, Layout, c }) }) } c.setRenderer(createRenderer(c, Layout, component, options)) diff --git a/yarn.lock b/yarn.lock index 442686c4..1174ff11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2197,18 +2197,18 @@ __metadata: dependencies: "@arethetypeswrong/cli": "npm:^0.17.4" "@cloudflare/vitest-pool-workers": "npm:^0.7.8" - "@types/react": "npm:^18" - "@types/react-dom": "npm:^18.2.17" + "@types/react": "npm:^19.1.0" + "@types/react-dom": "npm:^19.1.2" publint: "npm:^0.3.9" - react: "npm:^18.2.0" - react-dom: "npm:^18.2.0" + react: "npm:^19.1.0" + react-dom: "npm:^19.1.0" tsup: "npm:^8.4.0" typescript: "npm:^5.8.2" vitest: "npm:^3.0.8" peerDependencies: hono: "*" - react: "*" - react-dom: "*" + react: ^19.0.0 + react-dom: ^19.0.0 languageName: unknown linkType: soft @@ -3924,12 +3924,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18.2.17": - version: 18.3.5 - resolution: "@types/react-dom@npm:18.3.5" +"@types/react-dom@npm:^19.1.2": + version: 19.1.2 + resolution: "@types/react-dom@npm:19.1.2" peerDependencies: - "@types/react": ^18.0.0 - checksum: b163d35a6b32a79f5782574a7aeb12a31a647e248792bf437e6d596e2676961c394c5e3c6e91d1ce44ae90441dbaf93158efb4f051c0d61e2612f1cb04ce4faa + "@types/react": ^19.0.0 + checksum: 100c341cacba9ec8ae1d47ee051072a3450e9573bf8eeb7262490e341cb246ea0f95a07a1f2077e61cf92648f812a0324c602fcd811bd87b7ce41db2811510cd languageName: node linkType: hard @@ -3943,6 +3943,15 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:^19.1.0": + version: 19.1.0 + resolution: "@types/react@npm:19.1.0" + dependencies: + csstype: "npm:^3.0.2" + checksum: 632fd20ee176e55801a61c5f854141b043571a3e363ef106b047b766a813a12735cbb37abb3d61d126346979f530f2ed269a60c8ef3cdee54e5e9fe4174e5dad + languageName: node + linkType: hard + "@types/request@npm:^2.48.8": version: 2.48.12 resolution: "@types/request@npm:2.48.12" @@ -11882,15 +11891,14 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^18.2.0": - version: 18.3.1 - resolution: "react-dom@npm:18.3.1" +"react-dom@npm:^19.1.0": + version: 19.1.0 + resolution: "react-dom@npm:19.1.0" dependencies: - loose-envify: "npm:^1.1.0" - scheduler: "npm:^0.23.2" + scheduler: "npm:^0.26.0" peerDependencies: - react: ^18.3.1 - checksum: a752496c1941f958f2e8ac56239172296fcddce1365ce45222d04a1947e0cc5547df3e8447f855a81d6d39f008d7c32eab43db3712077f09e3f67c4874973e85 + react: ^19.1.0 + checksum: 3e26e89bb6c67c9a6aa86cb888c7a7f8258f2e347a6d2a15299c17eb16e04c19194e3452bc3255bd34000a61e45e2cb51e46292392340432f133e5a5d2dfb5fc languageName: node linkType: hard @@ -11903,6 +11911,13 @@ __metadata: languageName: node linkType: hard +"react@npm:^19.1.0": + version: 19.1.0 + resolution: "react@npm:19.1.0" + checksum: 530fb9a62237d54137a13d2cfb67a7db6a2156faed43eecc423f4713d9b20c6f2728b026b45e28fcd72e8eadb9e9ed4b089e99f5e295d2f0ad3134251bdd3698 + languageName: node + linkType: hard + "read-yaml-file@npm:^1.1.0": version: 1.1.0 resolution: "read-yaml-file@npm:1.1.0" @@ -12610,12 +12625,10 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.23.2": - version: 0.23.2 - resolution: "scheduler@npm:0.23.2" - dependencies: - loose-envify: "npm:^1.1.0" - checksum: 26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78 +"scheduler@npm:^0.26.0": + version: 0.26.0 + resolution: "scheduler@npm:0.26.0" + checksum: 5b8d5bfddaae3513410eda54f2268e98a376a429931921a81b5c3a2873aab7ca4d775a8caac5498f8cbc7d0daeab947cf923dbd8e215d61671f9f4e392d34356 languageName: node linkType: hard