Skip to content

Commit 92574d3

Browse files
committed
Move require into .cts
1 parent 57b064c commit 92574d3

File tree

4 files changed

+52
-51
lines changed

4 files changed

+52
-51
lines changed

node_package/src/ClientSideRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { RailsContext, RegisteredComponent, RenderFunction, Root } from './
77
import { getRailsContext, resetRailsContext } from './context.ts';
88
import createReactOutput from './createReactOutput.ts';
99
import { isServerRenderHash } from './isServerRenderResult.ts';
10-
import { supportsRootApi } from './reactApis.ts';
10+
import { supportsRootApi } from './reactApis.cts';
1111
import reactHydrateOrRender from './reactHydrateOrRender.ts';
1212
import { debugTurbolinks } from './turbolinksUtils.ts';
1313
import * as StoreRegistry from './StoreRegistry.ts';

node_package/src/reactApis.cts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as ReactDOM from 'react-dom';
2+
import type { ReactElement } from 'react';
3+
import type { RenderReturnType } from './types/index.ts' with { 'resolution-mode': 'import' };
4+
5+
const reactMajorVersion = Number(ReactDOM.version?.split('.')[0]) || 16;
6+
7+
// TODO: once we require React 18, we can remove this and inline everything guarded by it.
8+
// Not the default export because others may be added for future React versions.
9+
// eslint-disable-next-line import/prefer-default-export
10+
export const supportsRootApi = reactMajorVersion >= 18;
11+
12+
// TODO: once React dependency is updated to >= 18, we can remove this and just
13+
// import ReactDOM from 'react-dom/client';
14+
let reactDomClient: typeof import('react-dom/client');
15+
if (supportsRootApi) {
16+
// This will never throw an exception, but it's the way to tell Webpack the dependency is optional
17+
// https://github.com/webpack/webpack/issues/339#issuecomment-47739112
18+
// Unfortunately, it only converts the error to a warning.
19+
try {
20+
// eslint-disable-next-line global-require,@typescript-eslint/no-require-imports
21+
reactDomClient = require('react-dom/client') as typeof import('react-dom/client');
22+
} catch (_e) {
23+
// We should never get here, but if we do, we'll just use the default ReactDOM
24+
// and live with the warning.
25+
reactDomClient = ReactDOM as unknown as typeof import('react-dom/client');
26+
}
27+
}
28+
29+
type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
30+
31+
/* eslint-disable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion --
32+
* while we need to support React 16
33+
*/
34+
const hydrateProp = 'hydrate';
35+
const renderProp = 'render';
36+
37+
export const reactHydrate: HydrateOrRenderType = supportsRootApi
38+
? reactDomClient!.hydrateRoot
39+
: (domNode, reactElement) => ReactDOM[hydrateProp](reactElement, domNode);
40+
41+
export function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
42+
if (supportsRootApi) {
43+
const root = reactDomClient!.createRoot(domNode);
44+
root.render(reactElement);
45+
return root;
46+
}
47+
48+
return ReactDOM[renderProp](reactElement, domNode);
49+
}
50+
/* eslint-enable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion */

node_package/src/reactApis.ts

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

node_package/src/reactHydrateOrRender.ts

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,6 @@
11
import type { ReactElement } from 'react';
2-
import * as ReactDOM from 'react-dom';
32
import type { RenderReturnType } from './types/index.ts';
4-
import { supportsRootApi } from './reactApis.ts';
5-
6-
type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
7-
8-
// TODO: once React dependency is updated to >= 18, we can remove this and just
9-
// import ReactDOM from 'react-dom/client';
10-
let reactDomClient: typeof import('react-dom/client');
11-
if (supportsRootApi) {
12-
// This will never throw an exception, but it's the way to tell Webpack the dependency is optional
13-
// https://github.com/webpack/webpack/issues/339#issuecomment-47739112
14-
// Unfortunately, it only converts the error to a warning.
15-
try {
16-
// eslint-disable-next-line global-require,@typescript-eslint/no-require-imports
17-
reactDomClient = require('react-dom/client') as typeof import('react-dom/client');
18-
} catch (_e) {
19-
// We should never get here, but if we do, we'll just use the default ReactDOM
20-
// and live with the warning.
21-
reactDomClient = ReactDOM as unknown as typeof import('react-dom/client');
22-
}
23-
}
24-
25-
/* eslint-disable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion --
26-
* while we need to support React 16
27-
*/
28-
const hydrateProp = 'hydrate';
29-
const renderProp = 'render';
30-
31-
const reactHydrate: HydrateOrRenderType = supportsRootApi
32-
? reactDomClient!.hydrateRoot
33-
: (domNode, reactElement) => ReactDOM[hydrateProp](reactElement, domNode);
34-
35-
function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
36-
if (supportsRootApi) {
37-
const root = reactDomClient!.createRoot(domNode);
38-
root.render(reactElement);
39-
return root;
40-
}
41-
42-
return ReactDOM[renderProp](reactElement, domNode);
43-
}
44-
/* eslint-enable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion */
3+
import { reactHydrate, reactRender } from './reactApis.cts';
454

465
export default function reactHydrateOrRender(
476
domNode: Element,

0 commit comments

Comments
 (0)