Skip to content

Commit

Permalink
Fix the render return type
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyr committed Jun 23, 2022
1 parent 745b3f2 commit 4472f2f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 48 deletions.
9 changes: 5 additions & 4 deletions node_package/src/ReactOnRails.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ReactElement, Component } from 'react';
import type { ReactElement } from 'react';

import * as ClientStartup from './clientStartup';
import handleError from './handleError';
Expand All @@ -13,11 +13,12 @@ import type {
RegisteredComponent,
RenderParams,
RenderResult,
RenderReturnType,
ErrorOptions,
ReactComponentOrRenderFunction,
AuthenticityHeaders,
StoreGenerator
} from './types/index';
StoreGenerator,
} from './types';
import reactHydrateOrRender from './reactHydrateOrRender';

/* eslint-disable @typescript-eslint/no-explicit-any */
Expand Down Expand Up @@ -183,7 +184,7 @@ ctx.ReactOnRails = {
* @param hydrate Pass truthy to update server rendered html. Default is falsy
* @returns {virtualDomElement} Reference to your component's backing instance
*/
render(name: string, props: Record<string, string>, domNodeId: string, hydrate: boolean): void | Element | Component {
render(name: string, props: Record<string, string>, domNodeId: string, hydrate: boolean): RenderReturnType {
const componentObj = ComponentRegistry.get(name);
const reactElement = createReactOutput({ componentObj, props, domNodeId });

Expand Down
84 changes: 42 additions & 42 deletions node_package/src/reactHydrateOrRender.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import { ReactElement, Component } from 'react';
import ReactDOM from 'react-dom';

type HydrateOrRenderReturnType = void | Element | Component;
type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => HydrateOrRenderReturnType;
const supportsReactCreateRoot = parseInt(ReactDOM.version.split('.')[0], 10) >= 18;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let reactDomClient: any;
if (supportsReactCreateRoot) {
// eslint-disable-next-line camelcase
if (__webpack_require__) {
// we are in a Webpack environment (and in a node-modules directory of another project)
// See https://webpack.js.org/guides/dependency-management/#context-module-api
const reactDomContext = require.context('react-dom/', false, /^client\.js$/);
reactDomClient = reactDomContext('react-dom/client.js');
} else {
// we want a dynamic require here so that webpack doesn't rewrite it
const reactDomClientName = 'react-dom/client';
// eslint-disable-next-line global-require,import/no-dynamic-require
reactDomClient = require(reactDomClientName);
}
}

export const reactHydrate: HydrateOrRenderType = supportsReactCreateRoot ?
reactDomClient.hydrateRoot :
(domNode, reactElement) => ReactDOM.hydrate(reactElement, domNode);

export function reactRender(domNode: Element, reactElement: ReactElement): HydrateOrRenderReturnType {
if (supportsReactCreateRoot) {
const root = reactDomClient.createRoot(domNode);
root.render(reactElement);
return root;
}

// eslint-disable-next-line react/no-render-return-value
return ReactDOM.render(reactElement, domNode);
}

export default function reactHydrateOrRender(shouldHydrate: boolean, domNode: Element, reactElement: ReactElement): HydrateOrRenderReturnType {
return shouldHydrate ? reactHydrate(domNode, reactElement) : reactRender(domNode, reactElement);
}
import type { ReactElement } from 'react';
import ReactDOM from 'react-dom';
import type { RenderReturnType } from './types';

type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
const supportsReactCreateRoot = parseInt(ReactDOM.version.split('.')[0], 10) >= 18;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let reactDomClient: any;
if (supportsReactCreateRoot) {
// eslint-disable-next-line camelcase
if (__webpack_require__) {
// we are in a Webpack environment (and in a node-modules directory of another project)
// See https://webpack.js.org/guides/dependency-management/#context-module-api
const reactDomContext = require.context('react-dom/', false, /^client\.js$/);
reactDomClient = reactDomContext('react-dom/client.js');
} else {
// we want a dynamic require here so that webpack doesn't rewrite it
const reactDomClientName = 'react-dom/client';
// eslint-disable-next-line global-require,import/no-dynamic-require
reactDomClient = require(reactDomClientName);
}
}

export const reactHydrate: HydrateOrRenderType = supportsReactCreateRoot ?
reactDomClient.hydrateRoot :
(domNode, reactElement) => ReactDOM.hydrate(reactElement, domNode);

export function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
if (supportsReactCreateRoot) {
const root = reactDomClient.createRoot(domNode);
root.render(reactElement);
return root;
}

// eslint-disable-next-line react/no-render-return-value
return ReactDOM.render(reactElement, domNode);
}

export default function reactHydrateOrRender(shouldHydrate: boolean, domNode: Element, reactElement: ReactElement): RenderReturnType {
return shouldHydrate ? reactHydrate(domNode, reactElement) : reactRender(domNode, reactElement);
}
12 changes: 10 additions & 2 deletions node_package/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ReactElement, Component, FunctionComponent, ComponentClass } from 'react';
import type { ReactElement, ReactNode, Component, FunctionComponent, ComponentClass } from 'react';

// Don't import redux just for the type definitions
// See https://github.com/shakacode/react_on_rails/issues/1321
Expand Down Expand Up @@ -112,6 +112,14 @@ export interface RenderResult {
renderingError?: RenderingError;
}

// from react-dom 18
export interface Root {
render(children: ReactNode): void;
unmount(): void;
}

export type RenderReturnType = void | Element | Component | Root;

export interface ReactOnRails {
register(components: { [id: string]: ReactComponentOrRenderFunction }): void;
registerStore(stores: { [id: string]: Store }): void;
Expand All @@ -126,7 +134,7 @@ export interface ReactOnRails {
clearHydratedStores(): void;
render(
name: string, props: Record<string, string>, domNodeId: string, hydrate: boolean
): void | Element | Component;
): RenderReturnType;
getComponent(name: string): RegisteredComponent;
serverRenderReactComponent(options: RenderParams): null | string | Promise<RenderResult>;
handleError(options: ErrorOptions): string | undefined;
Expand Down

0 comments on commit 4472f2f

Please sign in to comment.