Skip to content

Commit e43626d

Browse files
committed
Require createRoot/hydrateRoot from 'react-dom/client' under react-dom 18+
Fixes #1441
1 parent 3c7751c commit e43626d

File tree

10 files changed

+43
-101
lines changed

10 files changed

+43
-101
lines changed

node_package/src/ReactOnRails.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import type {
1818
AuthenticityHeaders,
1919
StoreGenerator
2020
} from './types/index';
21-
import reactHydrate from './reactHydrate';
22-
import reactRender from './reactRender';
21+
import reactHydrateOrRender from './reactHydrateOrRender';
2322

2423
/* eslint-disable @typescript-eslint/no-explicit-any */
2524
type Store = any;
@@ -188,9 +187,7 @@ ctx.ReactOnRails = {
188187
const componentObj = ComponentRegistry.get(name);
189188
const reactElement = createReactOutput({ componentObj, props, domNodeId });
190189

191-
const render = hydrate ? reactHydrate : reactRender;
192-
// eslint-disable-next-line react/no-render-return-value
193-
return render(document.getElementById(domNodeId) as Element, reactElement as ReactElement);
190+
return reactHydrateOrRender(hydrate, document.getElementById(domNodeId) as Element, reactElement as ReactElement);
194191
},
195192

196193
/**

node_package/src/clientStartup.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import type {
99

1010
import createReactOutput from './createReactOutput';
1111
import {isServerRenderHash} from './isServerRenderResult';
12-
import reactHydrate from './reactHydrate';
13-
import reactRender from './reactRender';
12+
import reactHydrateOrRender from './reactHydrateOrRender';
1413

1514
declare global {
1615
interface Window {
@@ -168,10 +167,8 @@ function render(el: Element, railsContext: RailsContext): void {
168167
throw new Error(`\
169168
You returned a server side type of react-router error: ${JSON.stringify(reactElementOrRouterResult)}
170169
You should return a React.Component always for the client side entry point.`);
171-
} else if (shouldHydrate) {
172-
reactHydrate(domNode, reactElementOrRouterResult as ReactElement);
173170
} else {
174-
reactRender(domNode, reactElementOrRouterResult as ReactElement);
171+
reactHydrateOrRender(shouldHydrate, domNode, reactElementOrRouterResult as ReactElement);
175172
}
176173
}
177174
} catch (e: any) {

node_package/src/reactHydrate.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { ReactElement, Component } from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
type RenderReturnType = void | Element | Component;
5+
type ReactHydrateOrRender = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
6+
const supportsReactCreateRoot = parseInt(ReactDOM.version.split('.')[0], 10) >= 18;
7+
8+
// See https://webpack.js.org/guides/dependency-management/#context-module-api
9+
const reactDomContext = require.context('../node_modules/', false, /^client\.js$/);
10+
const reactDomClient = supportsReactCreateRoot ? reactDomContext('../node_modules/client.js') : undefined;
11+
export const reactHydrate: ReactHydrateOrRender = supportsReactCreateRoot ?
12+
reactDomClient.hydrateRoot :
13+
(domNode, reactElement) => ReactDOM.hydrate(reactElement, domNode);
14+
15+
export function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
16+
if (supportsReactCreateRoot) {
17+
const root = reactDomClient.createRoot(domNode);
18+
root.render(reactElement);
19+
return root;
20+
}
21+
22+
// eslint-disable-next-line react/no-render-return-value
23+
return ReactDOM.render(reactElement, domNode);
24+
}
25+
26+
export default function reactHydrateOrRender(shouldHydrate: boolean, domNode: Element, reactElement: ReactElement): RenderReturnType {
27+
return shouldHydrate ? reactHydrate(domNode, reactElement) : reactRender(domNode, reactElement);
28+
}

node_package/src/reactRender.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

node_package/src/supportsReactCreateRoot.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

node_package/tests/supportsReactCreateRoot.test.js

Lines changed: 0 additions & 44 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
"@babel/preset-react": "^7.12.10",
1616
"@babel/types": "^7.12.10",
1717
"@types/jest": "^26.0.18",
18-
"@types/node": "^14.14.11",
1918
"@types/react": "^16.9.23",
2019
"@types/react-dom": "^16.9.5",
2120
"@types/turbolinks": "^5.2.0",
21+
"@types/webpack-env": "^1.17.0",
2222
"@typescript-eslint/eslint-plugin": "^4.10.0",
2323
"@typescript-eslint/parser": "^4.10.0",
2424
"babelify": "^10.0.0",

spec/dummy/yarn.lock

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6349,7 +6349,7 @@ react-is@^16.7.0:
63496349
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
63506350

63516351
"react-on-rails@file:.yalc/react-on-rails":
6352-
version "13.0.1"
6352+
version "13.0.2"
63536353
dependencies:
63546354
"@babel/runtime-corejs3" "^7.12.5"
63556355
concurrently "^5.1.0"
@@ -6983,11 +6983,10 @@ sha.js@^2.4.0, sha.js@^2.4.8:
69836983
inherits "^2.0.1"
69846984
safe-buffer "^5.0.1"
69856985

6986-
6987-
name shakapacker
6988-
version "6.4.0"
6989-
resolved "https://registry.yarnpkg.com/shakapacker/-/shakapacker-6.4.0.tgz#f49ad8bb51eb1a151b190b588ad467c6e6f62e69"
6990-
integrity sha512-bxxi7Lla3n2fnFjxVv6BtD2vcTEZIm2eb29WkJqZBmpFVT9tnwbd3XQISD9eOst6kTEJu2ruUp7dGvuEjpxwkg==
6986+
shakapacker@^6.4.0:
6987+
version "6.4.1"
6988+
resolved "https://registry.yarnpkg.com/shakapacker/-/shakapacker-6.4.1.tgz#4c3662c63acf54ecd7847f97ceb88ee1a23bfa2a"
6989+
integrity sha512-yCGqDVNP5Dz4W8wAl53M/zG6/xpvAaFItPVVlDuHyq3xCzHD2MYEBvmITNgBvvl2WU34OPcEIeVrXOWcl/MCMQ==
69916990
dependencies:
69926991
glob "^7.2.0"
69936992
js-yaml "^4.1.0"

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,11 +1594,6 @@
15941594
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.35.tgz#42c953a4e2b18ab931f72477e7012172f4ffa313"
15951595
integrity sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==
15961596

1597-
"@types/node@^14.14.11":
1598-
version "14.14.11"
1599-
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.11.tgz#fc25a4248a5e8d0837019b1d170146d07334abe0"
1600-
integrity sha512-BJ97wAUuU3NUiUCp44xzUFquQEvnk1wu7q4CMEUYKJWjdkr0YWYDsm4RFtAvxYsNjLsKcrFt6RvK8r+mnzMbEQ==
1601-
16021597
"@types/normalize-package-data@^2.4.0":
16031598
version "2.4.0"
16041599
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
@@ -1639,6 +1634,11 @@
16391634
resolved "https://registry.yarnpkg.com/@types/turbolinks/-/turbolinks-5.2.0.tgz#cdfd3691143ea2f452113c2a06bd12d9a88b25d6"
16401635
integrity sha512-xEgHb25lj23EaUlsU3Y4KlFH7elhlYINGSnqyn/8zmcMnenY4Idyjk/x9kw1kOoOToY3de9fD8NSwRzNc6f5nw==
16411636

1637+
"@types/webpack-env@^1.17.0":
1638+
version "1.17.0"
1639+
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.17.0.tgz#f99ce359f1bfd87da90cc4a57cab0a18f34a48d0"
1640+
integrity sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==
1641+
16421642
"@types/yargs-parser@*":
16431643
version "20.2.0"
16441644
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"

0 commit comments

Comments
 (0)