Skip to content

Commit fa48d6f

Browse files
improve naming and organization
1 parent 448cd5d commit fa48d6f

File tree

1 file changed

+53
-50
lines changed

1 file changed

+53
-50
lines changed

node_package/src/serverRenderReactComponent.ts

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,42 @@ import type { CreateReactOutputResult, RegisteredComponent, RenderParams, Render
1111
type RenderState = {
1212
result: null | string | Promise<string>;
1313
hasErrors: boolean;
14-
error: null | RenderingError;
14+
error?: RenderingError;
1515
};
1616

1717
type RenderOptions = {
18-
name: string;
18+
componentName: string;
1919
domNodeId?: string;
2020
trace?: boolean;
2121
renderingReturnsPromises: boolean;
2222
};
2323

24-
function validateComponent(componentObj: RegisteredComponent, name: string) {
24+
function validateComponent(componentObj: RegisteredComponent, componentName: string) {
2525
if (componentObj.isRenderer) {
26-
throw new Error(`Detected a renderer while server rendering component '${name}'. See https://github.com/shakacode/react_on_rails#renderer-functions`);
26+
throw new Error(`Detected a renderer while server rendering component '${componentName}'. See https://github.com/shakacode/react_on_rails#renderer-functions`);
2727
}
2828
}
2929

30-
function processServerRenderHash(result: ServerRenderResult, options: RenderOptions): string {
30+
function processServerRenderHash(result: ServerRenderResult, options: RenderOptions): RenderState {
3131
const { redirectLocation, routeError } = result;
3232
const hasErrors = !!routeError;
3333

3434
if (hasErrors) {
3535
console.error(`React Router ERROR: ${JSON.stringify(routeError)}`);
3636
}
3737

38+
let htmlResult: string;
3839
if (redirectLocation) {
3940
if (options.trace) {
4041
const redirectPath = redirectLocation.pathname + redirectLocation.search;
41-
console.log(`ROUTER REDIRECT: ${options.name} to dom node with id: ${options.domNodeId}, redirect to ${redirectPath}`);
42+
console.log(`ROUTER REDIRECT: ${options.componentName} to dom node with id: ${options.domNodeId}, redirect to ${redirectPath}`);
4243
}
43-
return '';
44+
htmlResult = '';
45+
} else {
46+
htmlResult = result.renderedHtml as string;
4447
}
4548

46-
return result.renderedHtml as string;
49+
return { result: htmlResult, hasErrors };
4750
}
4851

4952
function processPromise(result: Promise<unknown>, renderingReturnsPromises: boolean): Promise<string> | string {
@@ -67,79 +70,78 @@ as a renderFunction and not a simple React Function Component.`);
6770
}
6871
}
6972

70-
function processRenderingResult(result: CreateReactOutputResult, options: RenderOptions): string | Promise<string> {
73+
function processRenderingResult(result: CreateReactOutputResult, options: RenderOptions): RenderState {
7174
if (isServerRenderHash(result)) {
7275
return processServerRenderHash(result, options);
7376
}
7477
if (isPromise(result)) {
75-
return processPromise(result, options.renderingReturnsPromises);
78+
return { result: processPromise(result, options.renderingReturnsPromises), hasErrors: false };
7679
}
77-
return processReactElement(result);
80+
return { result: processReactElement(result), hasErrors: false };
7881
}
7982

80-
function handleRenderingError(e: Error, renderState: RenderState, options: { name: string, throwJsErrors: boolean }) {
83+
function handleRenderingError(e: unknown, options: { componentName: string, throwJsErrors: boolean }) {
8184
if (options.throwJsErrors) {
8285
throw e;
8386
}
87+
const error = e instanceof Error ? e : new Error(String(e));
8488
return {
85-
...renderState,
8689
hasErrors: true,
87-
result: handleError({ e, name: options.name, serverSide: true }),
88-
error: e,
90+
result: handleError({ e: error, name: options.componentName, serverSide: true }),
91+
error,
8992
};
9093
}
9194

92-
function createResultObject(html: string | null, consoleReplayScript: string, hasErrors: boolean, error: RenderingError | null): RenderResult {
93-
const result: RenderResult = { html, consoleReplayScript, hasErrors };
94-
if (error) {
95-
result.renderingError = {
96-
message: error.message,
97-
stack: error.stack,
98-
};
99-
}
100-
return result;
101-
}
102-
103-
function createSyncResult(renderState: RenderState & { result: string | null }, consoleReplayScript: string): RenderResult {
104-
return createResultObject(renderState.result, consoleReplayScript, renderState.hasErrors, renderState.error);
95+
function createResultObject(html: string | null, consoleReplayScript: string, hasErrors: boolean, error?: RenderingError): RenderResult {
96+
return {
97+
html,
98+
consoleReplayScript,
99+
hasErrors,
100+
renderingError: error && { message: error.message, stack: error.stack },
101+
};
105102
}
106103

107-
function createPromiseResult(renderState: RenderState & { result: Promise<string> }, consoleReplayScript: string): Promise<RenderResult> {
108-
return (async () => {
109-
try {
110-
const html = await renderState.result;
111-
return createResultObject(html, consoleReplayScript, renderState.hasErrors, renderState.error);
112-
} catch (e: unknown) {
113-
const error = e instanceof Error ? e : new Error(String(e));
114-
const html = handleError({ e: error, name: 'Unknown', serverSide: true });
115-
return createResultObject(html, consoleReplayScript, true, error);
116-
}
117-
})();
104+
async function createPromiseResult(
105+
renderState: RenderState & { result: Promise<string> },
106+
consoleReplayScript: string,
107+
componentName: string,
108+
throwJsErrors: boolean
109+
): Promise<RenderResult> {
110+
try {
111+
const html = await renderState.result;
112+
return createResultObject(html, consoleReplayScript, renderState.hasErrors, renderState.error);
113+
} catch (e: unknown) {
114+
const errorRenderState = handleRenderingError(e, { componentName, throwJsErrors });
115+
return createResultObject(errorRenderState.result, consoleReplayScript, errorRenderState.hasErrors, errorRenderState.error);
116+
}
118117
}
119118

120-
function createFinalResult(renderState: RenderState): null | string | Promise<RenderResult> {
119+
function createFinalResult(
120+
renderState: RenderState,
121+
componentName: string,
122+
throwJsErrors: boolean
123+
): null | string | Promise<RenderResult> {
121124
const consoleReplayScript = buildConsoleReplay();
122125

123126
const { result } = renderState;
124127
if (isPromise(result)) {
125-
return createPromiseResult({ ...renderState, result }, consoleReplayScript);
128+
return createPromiseResult({ ...renderState, result }, consoleReplayScript, componentName, throwJsErrors);
126129
}
127130

128-
return JSON.stringify(createSyncResult({ ...renderState, result }, consoleReplayScript));
131+
return JSON.stringify(createResultObject(result, consoleReplayScript, renderState.hasErrors, renderState.error));
129132
}
130133

131134
function serverRenderReactComponentInternal(options: RenderParams): null | string | Promise<RenderResult> {
132-
const { name, domNodeId, trace, props, railsContext, renderingReturnsPromises, throwJsErrors } = options;
135+
const { name: componentName, domNodeId, trace, props, railsContext, renderingReturnsPromises, throwJsErrors } = options;
133136

134137
let renderState: RenderState = {
135138
result: null,
136139
hasErrors: false,
137-
error: null,
138140
};
139141

140142
try {
141-
const componentObj = ComponentRegistry.get(name);
142-
validateComponent(componentObj, name);
143+
const componentObj = ComponentRegistry.get(componentName);
144+
validateComponent(componentObj, componentName);
143145

144146
// Renders the component or executes the render function
145147
// - If the registered component is a React element or component, it renders it
@@ -149,13 +151,14 @@ function serverRenderReactComponentInternal(options: RenderParams): null | strin
149151
// - For other values (e.g., strings), it returns them directly
150152
// Note: Only synchronous operations are performed at this stage
151153
const reactRenderingResult = createReactOutput({ componentObj, domNodeId, trace, props, railsContext });
154+
152155
// Processes the result from createReactOutput:
153156
// 1. Converts React elements to HTML strings
154157
// 2. Returns rendered HTML from serverRenderHash
155158
// 3. Handles promises for async rendering
156-
renderState.result = processRenderingResult(reactRenderingResult, { name, domNodeId, trace, renderingReturnsPromises });
157-
} catch (e) {
158-
renderState = handleRenderingError(e as Error, renderState, { name, throwJsErrors });
159+
renderState = processRenderingResult(reactRenderingResult, { componentName, domNodeId, trace, renderingReturnsPromises });
160+
} catch (e: unknown) {
161+
renderState = handleRenderingError(e, { componentName, throwJsErrors });
159162
}
160163

161164
// Finalize the rendering result and prepare it for server response
@@ -167,7 +170,7 @@ function serverRenderReactComponentInternal(options: RenderParams): null | strin
167170
// - hasErrors: boolean (Indicates if any errors occurred during rendering)
168171
// - renderingError: Error | null (The error object if an error occurred, null otherwise)
169172
// 4. For Promise results, it awaits resolution before creating the final JSON
170-
return createFinalResult(renderState);
173+
return createFinalResult(renderState, componentName, throwJsErrors);
171174
}
172175

173176
const serverRenderReactComponent: typeof serverRenderReactComponentInternal = (options) => {

0 commit comments

Comments
 (0)