Skip to content

Commit 53921c4

Browse files
justin808claude
andcommitted
fix: Pass railsContext and guard against async renders in render() method
Fixes a critical regression where the render() method was not passing railsContext to createReactOutput(), causing render functions that depend on railsContext (e.g., for location, locale) to receive undefined. Also adds guards for: - Server render hash objects (react-router errors) - Promise returns (async render functions) These guards ensure the synchronous render() API doesn't silently accept async operations that should use reactOnRailsComponentLoaded() instead. Addresses code review comment from PR #1834: #1834 (comment) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0b30c04 commit 53921c4

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

packages/react-on-rails/src/base/client.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import * as Authenticity from '../Authenticity.ts';
1313
import buildConsoleReplay from '../buildConsoleReplay.ts';
1414
import reactHydrateOrRender from '../reactHydrateOrRender.ts';
1515
import createReactOutput from '../createReactOutput.ts';
16+
import { getRailsContext } from '../context.ts';
17+
import { isPromise, isServerRenderHash } from '../isServerRenderResult.ts';
1618

1719
const DEFAULT_OPTIONS = {
1820
traceTurbolinks: false,
@@ -266,7 +268,30 @@ Fix: Use only react-on-rails OR react-on-rails-pro, not both.`);
266268
hydrate: boolean,
267269
): RenderReturnType {
268270
const componentObj = ComponentRegistry.get(name);
269-
const reactElement = createReactOutput({ componentObj, props, domNodeId });
271+
const railsContext = getRailsContext();
272+
const reactElement = createReactOutput({
273+
componentObj,
274+
props,
275+
domNodeId,
276+
railsContext: railsContext ?? undefined,
277+
shouldHydrate: hydrate,
278+
});
279+
280+
// Guard against server render hash (shouldn't happen in client, but check anyway)
281+
if (isServerRenderHash(reactElement)) {
282+
throw new Error(
283+
`You returned a server side type of react-router error: ${JSON.stringify(reactElement)}\n` +
284+
'You should return a React.Component always for the client side entry point.',
285+
);
286+
}
287+
288+
// Guard against promises (not supported in this sync API)
289+
if (isPromise(reactElement)) {
290+
throw new Error(
291+
'Async render functions are not supported in ReactOnRails.render(). ' +
292+
'Use ReactOnRails.reactOnRailsComponentLoaded() for async component rendering.',
293+
);
294+
}
270295

271296
return this.reactHydrateOrRender(
272297
document.getElementById(domNodeId) as Element,

0 commit comments

Comments
 (0)