UNPKG

react-on-rails

Version:

react-on-rails JavaScript for react_on_rails Ruby gem

175 lines (174 loc) 6.17 kB
import type { ReactElement, ReactNode, Component, ComponentType } from 'react'; import type { Readable } from 'stream'; type Store = unknown; type ReactComponent = ComponentType<any> | string; export interface RailsContext { railsEnv: string; inMailer: boolean; i18nLocale: string; i18nDefaultLocale: string; rorVersion: string; rorPro: boolean; rorProVersion?: string; serverSide: boolean; href: string; location: string; scheme: string; host: string; port: number | null; pathname: string; search: string | null; httpAcceptLanguage: string; } type AuthenticityHeaders = { [id: string]: string; } & { 'X-CSRF-Token': string | null; 'X-Requested-With': string; }; type StoreGenerator = (props: Record<string, unknown>, railsContext: RailsContext) => Store; interface ServerRenderResult { renderedHtml?: string | { componentHtml: string; [key: string]: string; }; redirectLocation?: { pathname: string; search: string; }; routeError?: Error; error?: Error; } type CreateReactOutputResult = ServerRenderResult | ReactElement | Promise<string>; type RenderFunctionResult = ReactComponent | ServerRenderResult | Promise<string>; /** * Render functions are used to create dynamic React components or server-rendered HTML with side effects. * They receive two arguments: props and railsContext. * * @param props - The component props passed to the render function * @param railsContext - The Rails context object containing environment information * @returns A string, React component, React element, or a Promise resolving to a string * * @remarks * To distinguish a render function from a React Function Component: * 1. Ensure it accepts two parameters (props and railsContext), even if railsContext is unused, or * 2. Set the `renderFunction` property to `true` on the function object. * * If neither condition is met, it will be treated as a React Function Component, * and ReactDOMServer will attempt to render it. * * @example * // Option 1: Two-parameter function * const renderFunction = (props, railsContext) => { ... }; * * // Option 2: Using renderFunction property * const anotherRenderFunction = (props) => { ... }; * anotherRenderFunction.renderFunction = true; */ interface RenderFunction { (props?: any, railsContext?: RailsContext, domNodeId?: string): RenderFunctionResult; renderFunction?: true; } type ReactComponentOrRenderFunction = ReactComponent | RenderFunction; export type { // eslint-disable-line import/prefer-default-export ReactComponentOrRenderFunction, ReactComponent, AuthenticityHeaders, RenderFunction, RenderFunctionResult, Store, StoreGenerator, CreateReactOutputResult, ServerRenderResult, }; export interface RegisteredComponent { name: string; component: ReactComponentOrRenderFunction; /** * Indicates if the registered component is a RenderFunction * @see RenderFunction for more details on its behavior and usage. */ renderFunction: boolean; isRenderer: boolean; } interface Params { props?: Record<string, unknown>; railsContext?: RailsContext; domNodeId?: string; trace?: boolean; } export interface RenderParams extends Params { name: string; throwJsErrors: boolean; renderingReturnsPromises: boolean; } export interface CreateParams extends Params { componentObj: RegisteredComponent; shouldHydrate?: boolean; } export interface ErrorOptions { e: Error & { fileName?: string; lineNumber?: string; }; name?: string; jsCode?: string; serverSide: boolean; } export type RenderingError = Pick<Error, 'message' | 'stack'>; export interface RenderResult { html: string | null; consoleReplayScript: string; hasErrors: boolean; renderingError?: RenderingError; isShellReady?: boolean; } 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; /** @deprecated Use registerStoreGenerators instead */ registerStore(stores: { [id: string]: StoreGenerator; }): void; registerStoreGenerators(storeGenerators: { [id: string]: StoreGenerator; }): void; getStore(name: string, throwIfMissing?: boolean): Store | undefined; setOptions(newOptions: { traceTurbolinks: boolean; }): void; reactHydrateOrRender(domNode: Element, reactElement: ReactElement, hydrate: boolean): RenderReturnType; reactOnRailsPageLoaded(): void; reactOnRailsComponentLoaded(domId: string): void; authenticityToken(): string | null; authenticityHeaders(otherHeaders: { [id: string]: string; }): AuthenticityHeaders; option(key: string): string | number | boolean | undefined; getStoreGenerator(name: string): StoreGenerator; setStore(name: string, store: Store): void; clearHydratedStores(): void; render(name: string, props: Record<string, string>, domNodeId: string, hydrate: boolean): RenderReturnType; getComponent(name: string): RegisteredComponent; serverRenderReactComponent(options: RenderParams): null | string | Promise<RenderResult>; streamServerRenderedReactComponent(options: RenderParams): Readable; handleError(options: ErrorOptions): string | undefined; buildConsoleReplay(): string; registeredComponents(): Map<string, RegisteredComponent>; storeGenerators(): Map<string, StoreGenerator>; stores(): Map<string, Store>; resetOptions(): void; options: Record<string, string | number | boolean>; } export type RenderState = { result: null | string | Promise<string>; hasErrors: boolean; error?: RenderingError; }; export type StreamRenderState = Omit<RenderState, 'result'> & { result: null | Readable; isShellReady: boolean; }; export type RenderOptions = { componentName: string; domNodeId?: string; trace?: boolean; renderingReturnsPromises: boolean; };