Skip to content

docs: fix render function/helper API documentation#3088

Merged
justin808 merged 5 commits intomainfrom
jg/2911-docs-render-api
Apr 12, 2026
Merged

docs: fix render function/helper API documentation#3088
justin808 merged 5 commits intomainfrom
jg/2911-docs-render-api

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented Apr 9, 2026

Summary

Comprehensive documentation fixes for render functions, renderer functions, view helpers, and component registration APIs. Addresses documentation gaps and inaccuracies identified in #2911.

Key changes:

  • Legacy markers: Mark redirectLocation/routeError as legacy (React Router v3/v4) with clear modern alternatives
  • Compatibility matrix: Add component type × Ruby helper compatibility table showing valid/invalid combinations
  • react_component_hash behavior: Document that it silently forces prerender: true
  • stream_react_component behavior: Document forced prerender: true and immediate_hydration: true
  • <Navigate> SSR behavior: Document that it's a no-op during SSR (renders null, redirect fires client-side only)
  • Async + ExecJS: Document that async render functions silently return '{}' with ExecJS
  • Server render hash detection: Document that error key triggers server-render-hash processing
  • JSX deprecation: Update outdated "v13 will throw error" reference
  • clientProps merge: Document symbol/string key handling and edge cases
  • registerServerComponent gotcha: Add prominent callout about different signatures per bundle (server takes object, client takes strings)
  • register() JSDoc: Rewrite with detection logic and complete return type documentation

Files changed:

File Changes
docs/oss/core-concepts/render-functions.md Legacy markers, compatibility matrix, edge case docs
docs/oss/api-reference/view-helpers-api.md Compatibility matrix ref, prerender forcing, stream docs
docs/oss/api-reference/javascript-api.md Rewritten register() JSDoc
docs/oss/getting-started/using-react-on-rails.md Fixed example, legacy note
docs/oss/building-features/react-router.md <Navigate> SSR behavior section
docs/pro/react-server-components/inside-client-components.md registerServerComponent signature gotcha

Closes #2911

Test plan

  • Verify all markdown renders correctly on the docs site
  • Verify internal doc links resolve (pre-push hook validated 55 links with 0 errors)
  • Review compatibility matrix accuracy against source code

🤖 Generated with Claude Code


Note

Low Risk
Docs-only updates clarifying helper/render-function contracts; low risk aside from potential confusion if guidance is inaccurate or links regress.

Overview
Updates OSS docs to correct and expand render-function and helper API guidance: rewrites ReactOnRails.register() JSDoc to explain component detection (param count / .renderFunction) and supported return shapes, and clarifies when render-functions vs renderer functions are valid.

Strengthens helper documentation by explicitly documenting forced behaviors and deprecations (e.g., react_component_hash and stream_react_component forcing prerender: true, immediate_hydration ignored with warning), marking redirectLocation/routeError as legacy with modern alternatives, and adding a compatibility matrix mapping return types to react_component/react_component_hash/stream_react_component.

Adds React Router SSR guidance for <Navigate> being a client-only redirect, fixes getting-started examples to match the { renderedHtml: { componentHtml, ... } } shape, and updates Pro RSC docs to highlight registerServerComponent’s different server vs client signatures (with corrected client example).

Reviewed by Cursor Bugbot for commit 489d433. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Documentation
    • Revised component registration API docs with a clear taxonomy of callable component types and accepted return shapes.
    • Clarified deprecation and legacy behavior for redirect/routeError, with migration guidance.
    • Updated react_component, react_component_hash, and stream_react_component docs: forced prerendering, compatibility matrix, immediate_hydration deprecation, and client-only renderer rules.
    • Documented React Router SSR behavior and recommended server-side redirects.
    • Clarified server/RSC registration signatures, client example simplification, clientProps hydration merge rules, and a hook/JSX return warning.

Address documentation gaps and inaccuracies across render function,
view helper, and component registration docs.

Key changes:
- Mark redirectLocation/routeError as legacy (React Router v3/v4) with
  modern alternatives documented
- Add component type x Ruby helper compatibility matrix
- Document react_component_hash silently forcing prerender: true
- Document stream_react_component forcing prerender + immediate_hydration
- Document Navigate component SSR behavior (no-op, client-only redirect)
- Document async render function + ExecJS silent failure
- Document isServerRenderResult broad detection (error key)
- Document JSX-returning render function deprecation status
- Document clientProps symbol/string key merge edge cases
- Add registerServerComponent per-bundle signature gotcha in Pro docs
- Update register() JSDoc with detection logic and return types

Closes #2911

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Documentation-only revisions clarifying component registration detection (parameter-count and .renderFunction), enumerating render-function/renderer-function return shapes and compatibility, deprecating legacy redirectLocation/routeError, documenting forced prerender behavior for react_component_hash/stream_react_component, noting registerServerComponent signature differences, and adding React Router <Navigate> SSR guidance.

Changes

Cohort / File(s) Summary
API Reference & View Helpers
docs/oss/api-reference/javascript-api.md, docs/oss/api-reference/view-helpers-api.md
Rewrote register(components) JSDoc to classify component types by parameter count and .renderFunction; enumerated server/client render return shapes and clientProps hydration; marked redirectLocation/routeError as legacy; documented that react_component_hash and stream_react_component force prerender: true and that 3-arg renderer functions are client-only/incompatible.
Core Concepts: Render Functions
docs/oss/core-concepts/render-functions.md
Renamed redirect sections to legacy and tightened legacy limitations; restricted async render-function behavior to Pro Node (ExecJS fallback noted); documented clientProps merge rules (symbol vs string key handling), broadened server-render-hash detection, deprecated returning JSX directly from render-functions, and added a Compatibility Matrix mapping return types to Ruby helpers.
Getting Started / Examples
docs/oss/getting-started/using-react-on-rails.md
Updated SSR examples to remove legacy redirectLocation/routeError in favor of renderedHtml fields (e.g., title/metaTags); stated react_component_hash always forces prerender; added deprecation pointers for legacy redirect fields.
React Router Guidance
docs/oss/building-features/react-router.md
Added guidance on React Router v6 <Navigate> SSR behavior: it renders null on server and triggers client-side navigation via useEffect; documented possible flash/no-HTTP-redirect behavior and recommended using Rails redirect_to for SSR/SEO-critical redirects.
Pro: Server Components / RSC
docs/pro/react-server-components/inside-client-components.md, docs/pro/react-server-components/create-without-ssr.md
Clarified registerServerComponent signature differences per bundle: Server/RSC bundles call registerServerComponent({ Name: Component }), client bundles register names only (e.g., registerServerComponent('Name')); simplified client example to remove client-side RSC payload URL config.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through docs with nimble feet,

Marked old redirects as legacy and neat.
Prerender forced, signatures split in two,
<Navigate> on server? It renders null—who knew.
A tiny rabbit hop to make things true.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing documentation for render function and helper APIs. It accurately reflects the content of the changeset.
Linked Issues check ✅ Passed The PR comprehensively addresses all major coding documentation objectives from issue #2911: clarifying render/renderer function distinctions, documenting react_component_hash prerender forcing, marking redirectLocation/routeError as legacy, adding compatibility matrices, documenting stream_react_component behavior, fixing registerServerComponent signature examples, documenting clientProps merge behavior, and explaining SSR behavior.
Out of Scope Changes check ✅ Passed All changes are documentation-only updates directly addressing the identified gaps and inaccuracies in issue #2911. No executable code was modified and all changes remain within scope of the API documentation objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jg/2911-docs-render-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread docs/oss/api-reference/view-helpers-api.md Outdated
Comment thread docs/pro/react-server-components/inside-client-components.md Outdated
Comment thread docs/oss/core-concepts/render-functions.md Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/oss/core-concepts/render-functions.md`:
- Line 252: The compatibility matrix entry claiming "Promise (any)" for
react_component_hash is inaccurate; update the table cell and related text to
require a Promise that resolves to the server-render-hash shape (e.g., an object
matching { renderedHtml: { componentHtml, ... } } after render-function
processing) rather than "any", and clarify that runtime errors may occur if the
resolved value doesn't match that shape; reference react_component_hash and the
"Render function → Promise" column when making this wording change.

In `@docs/pro/react-server-components/inside-client-components.md`:
- Line 72: Remove the empty blank line inside the warning blockquote in
inside-client-components.md (the quoted warning block that triggers MD028) so
the blockquote has no blank lines between ">" lines; simply delete the stray
empty quoted line to satisfy the no-blanks-blockquote rule and re-run
markdownlint to confirm the MD028 violation is resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2bab0dc7-9cbb-4f01-8ee3-a3eeeb6beb59

📥 Commits

Reviewing files that changed from the base of the PR and between 16ac897 and 0589c71.

📒 Files selected for processing (6)
  • docs/oss/api-reference/javascript-api.md
  • docs/oss/api-reference/view-helpers-api.md
  • docs/oss/building-features/react-router.md
  • docs/oss/core-concepts/render-functions.md
  • docs/oss/getting-started/using-react-on-rails.md
  • docs/pro/react-server-components/inside-client-components.md

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/pro/react-server-components/inside-client-components.md
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 9, 2026

Review Summary

Good overall: most documented behaviors are verified against source (component detection by parameter count, react_component_hash forcing prerender: true, ExecJS async silently returning '{}', server render result key detection, and clientProps merge/error behavior all confirmed accurate). The compatibility matrix and legacy callouts are helpful additions.

Two factual inaccuracies need fixing before merge:

1. stream_react_component and immediate_hydration

Both docs/oss/api-reference/view-helpers-api.md (line 163) and docs/oss/core-concepts/render-functions.md (line 258) claim:

stream_react_component always forces prerender: true and immediate_hydration: true

This is wrong. The Pro helper source (react_on_rails_pro_helper.rb) shows:

if options.key?(:immediate_hydration)
  ReactOnRails::Helper.warn_removed_immediate_hydration_option("stream_react_component")
  options.delete(:immediate_hydration)
end

immediate_hydration is a removed option — it gets deleted with a deprecation warning. The docs should say it is no longer supported, not that it is forced to true.

2. registerServerComponent client bundle signature

docs/pro/react-server-components/inside-client-components.md (line 69) documents the client signature as:

registerServerComponent({ rscPayloadGenerationUrlPath: '...' }, 'Name1', 'Name2')

The actual TypeScript signature in packages/react-on-rails-pro/src/registerServerComponent/client.tsx is:

const registerServerComponent = (...componentNames: string[]) => {

No options object is accepted. The rscPayloadGenerationUrlPath appears only in the JSDoc as an explanation of URL construction internals. Correct usage is just registerServerComponent('Name1', 'Name2').

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0589c718cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/pro/react-server-components/inside-client-components.md Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 9, 2026

Greptile Summary

This PR comprehensively improves the render-function and view-helper API documentation by adding legacy markers for redirectLocation/routeError, a new compatibility matrix, prerender-forcing behavior for react_component_hash and stream_react_component, a <Navigate> SSR behavior section, and a registerServerComponent signature callout. All behavioral claims were verified against source code (isRenderFunction.ts, isServerRenderResult.ts, helper.rb). One P2 inaccuracy exists in the new compatibility matrix: the Render function → Promise (any) row marks react_component_hash as supported, but only promises resolving to a server-side hash (Return Type 6) are valid — promises of React components or plain strings would cause a runtime error.

Confidence Score: 5/5

Safe to merge — documentation-only changes with one minor matrix inaccuracy that doesn't affect runtime behavior

All behavioral claims were verified against the source code. The single P2 finding (compatibility matrix overstating Promise support for react_component_hash) is a documentation nuance that doesn't cause silent failures — developers would get a visible runtime error. No executable code changed.

docs/oss/core-concepts/render-functions.md — the compatibility matrix row for Promise types

Vulnerabilities

No security concerns identified. This is a documentation-only PR with no changes to executable code.

Important Files Changed

Filename Overview
docs/oss/core-concepts/render-functions.md Major overhaul adding legacy markers, a new compatibility matrix, and Important Rendering Behavior notes; the "Promise (any)" matrix row overstates what works with react_component_hash
docs/oss/api-reference/view-helpers-api.md Accurate clarifications: prerender:true forcing for react_component_hash, stream_react_component constraints, and legacy deprecation note; all verified against source code
docs/oss/api-reference/javascript-api.md register() JSDoc rewritten with accurate parameter-count detection logic (verified against isRenderFunction.ts) and complete return type inventory
docs/oss/building-features/react-router.md New Navigate SSR behavior section is accurate: renders null, useEffect skipped during SSR, and React Router v6 does log a no-op warning in StaticRouter context
docs/oss/getting-started/using-react-on-rails.md Example corrected to use title/metaTags instead of redirectLocation/error, legacy deprecation note added; changes are accurate
docs/pro/react-server-components/inside-client-components.md registerServerComponent signature callout clearly documents the intentional server-vs-client bundle API difference; valuable addition

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Render Function return value] --> B{isServerRenderHash?}
    B -- "has renderedHtml / redirectLocation / routeError / error key" --> C[Server Render Hash path]
    B -- "no match" --> D{isPromise?}
    D -- yes --> E[Promise path\nPro Node renderer only]
    D -- no --> F[React Component path\ncreateReactOutput]

    C --> G{renderedHtml type?}
    G -- "string" --> H[react_component ✅]
    G -- "ReactElement" --> I[react_component prerender ✅]
    G -- "{ componentHtml, ...keys }" --> J[react_component_hash ✅]

    E --> K{resolves to?}
    K -- "string / React component" --> H
    K -- "{ componentHtml, ...keys }" --> J
    K -- "Promise of React component" --> H

    F --> L[react_component ✅\nstream_react_component ✅]
Loading

Reviews (1): Last reviewed commit: "docs: fix render function/helper API doc..." | Re-trigger Greptile

Comment thread docs/oss/core-concepts/render-functions.md Outdated
…nd Promise matrix

- Fix stream_react_component docs: immediate_hydration is a removed
  option (warns and deletes), not forced to true
- Fix registerServerComponent client signature: accepts variadic
  strings only, no options object
- Narrow "Promise (any)" to "Promise (compatible return shape)" for
  react_component_hash — only hash-shaped promises are valid

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed (ed159a9)

Three factual inaccuracies fixed, verified against source code:

  1. stream_react_component and immediate_hydration — The docs incorrectly said immediate_hydration: true is forced. The Pro helper source (react_on_rails_pro_helper.rb:131-133) shows the option is warned and deleted. Fixed in both view-helpers-api.md and render-functions.md.

  2. registerServerComponent client signature — Docs showed an options object as the first argument. The actual client source (client.tsx:51) accepts only (...componentNames: string[]). Fixed in inside-client-components.md.

  3. Promise "(any)" overstated for react_component_hash — Changed to "Promise (compatible return shape)" with a note that react_component_hash requires the promise to resolve to a hash with componentHtml.

Declined: Streaming Promise support claim (item 4) — needs full pipeline verification, deferred to follow-up.
Skipped: MD028 blank blockquote nit (between two separate blockquotes, not inside one).

All 8 review threads resolved with replies.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/oss/core-concepts/render-functions.md (1)

138-139: Consider varying sentence structure for improved readability.

The three consecutive sentences beginning with "For" create a repetitive pattern that slightly reduces readability.

✍️ Suggested rewording
 > **Modern alternatives:**
 >
-> - For redirects during SSR, handle them in your Rails controller (e.g., check auth before rendering).
+> - To handle redirects during SSR, check conditions in your Rails controller (e.g., auth checks before rendering).
 > - For client-side redirects, use `<Navigate to="/path" />` (note: this is a [no-op during SSR](../building-features/react-router.md#navigate-component-ssr-behavior)).
 > - For route errors, use React Router's `errorElement` or an `ErrorBoundary`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/core-concepts/render-functions.md` around lines 138 - 139, The three
consecutive sentences that start with "For" are repetitive; rephrase the
sentence that currently reads "For route errors, use React Router's
`errorElement` or an `ErrorBoundary`." to vary sentence structure — for example:
"Handle route errors by using React Router's `errorElement` or an
`ErrorBoundary`." — and update the surrounding two "For ..." sentences similarly
to avoid the repeated opener while keeping references to `errorElement` and
`ErrorBoundary`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/oss/core-concepts/render-functions.md`:
- Around line 138-139: The three consecutive sentences that start with "For" are
repetitive; rephrase the sentence that currently reads "For route errors, use
React Router's `errorElement` or an `ErrorBoundary`." to vary sentence structure
— for example: "Handle route errors by using React Router's `errorElement` or an
`ErrorBoundary`." — and update the surrounding two "For ..." sentences similarly
to avoid the repeated opener while keeping references to `errorElement` and
`ErrorBoundary`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4df9a7b3-c921-45ca-ad93-f53437e51c72

📥 Commits

Reviewing files that changed from the base of the PR and between 0589c71 and ed159a9.

📒 Files selected for processing (3)
  • docs/oss/api-reference/view-helpers-api.md
  • docs/oss/core-concepts/render-functions.md
  • docs/pro/react-server-components/inside-client-components.md
✅ Files skipped from review due to trivial changes (1)
  • docs/pro/react-server-components/inside-client-components.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/oss/api-reference/view-helpers-api.md

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 12, 2026

Review: docs/fix render function/helper API documentation

Overall this is a high-quality documentation PR — the compatibility matrix, clientProps merge clarifications, stream_react_component / react_component_hash behavior notes, and async+ExecJS gotcha are all accurate (verified against source). The registerServerComponent signature warning is a genuinely useful addition for Pro users. A few things warrant attention:


1. "Legacy (React Router v3/v4)" framing for redirectLocation/routeError is inaccurate

The PR labels these as deprecated legacy features, but they are actively handled in the current codebase with no deprecation markers:

  • serverRenderReactComponent.ts destructures and processes both fields in processServerRenderHash (lines 27–52)
  • types/index.ts defines them on ServerRenderResult without any @deprecated JSDoc tag (lines 129–130)
  • isServerRenderResult.ts explicitly checks for redirectLocation and routeError as primary server-render-hash detection keys

A developer writing a custom render function against React Router v6 (or any router) can still return these fields and they will be handled correctly. The PR correctly describes their limitations (no actual server-side redirect, routeError only triggers raise_on_prerender_error), but calling them a "Legacy feature from React Router v3/v4" overstates their obsolescence and may break working code for users who read this as "stop using this."

Suggestion: Keep the limitations section, but reframe from [!WARNING] / "Legacy" to a [!NOTE] explaining the limitations and pointing to Rails controller redirects as the preferred approach for auth/SEO — without declaring the feature deprecated when the code does not.


2. .renderFunction = true description is slightly misleading in the new JSDoc

The rewritten register() JSDoc says:

* - 2 params (or `.renderFunction = true`): Render-Function ...

This implies .renderFunction = true is an alias specifically for 2-param functions. In reality, the check in isRenderFunction.ts evaluates .renderFunction before the parameter-length check — a 1-param function with .renderFunction = true is also treated as a render function (skipping the railsContext parameter entirely). This pattern is already documented in render-functions.md and is common enough that the JSDoc should mention it clearly.


3. Minor: Compatibility matrix ❌ for react_component + { renderedHtml: { componentHtml, ... } }

The table shows ❌ for this combination, but react_component doesn't error on it — it silently renders the whole object as JSON text (garbled output). The ❌ implies a hard failure; a note clarifying "works but produces unexpected output" would help users diagnose the actual symptom.


4. Minor: using-react-on-rails.md example fix is good but the custom keys look prescriptive

The original had redirectLocation and error nested inside renderedHtml (which was wrong — they're top-level fields). The fix to title/metaTags is correct. Consider a brief comment that these are developer-defined custom keys, not framework-reserved names, so readers understand the pattern is open-ended:

renderedHtml: {
  componentHtml, // required — the main HTML string
  title,         // example custom key (any name works here)
  metaTags,      // example custom key (any name works here)
},

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/oss/api-reference/javascript-api.md Outdated
Comment thread docs/oss/building-features/react-router.md Outdated
Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/oss/core-concepts/render-functions.md
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ed159a9f31

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/pro/react-server-components/inside-client-components.md
… footnote, and legacy framing

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed (3c427ba)

I (Claude Code) addressed all 6 remaining review comments:

Accuracy fixes:

  1. javascript-api.md:30 — Fixed .renderFunction = true wording to clarify it works for any param count, not just 2-param functions (matches isRenderFunction.ts check order)
  2. react-router.md:188 — Removed unverifiable claim that <Navigate> "logs a warning in development mode" during SSR. Updated to explain the actual mechanism (useEffect doesn't fire on server)
  3. render-functions.md:241-244 — Added note below compatibility matrix: "❌ means silently produces incorrect output, not that it throws an error" with specific failure mode examples

Framing & detail improvements:
4. render-functions.md:127 — Changed [!WARNING] + "Legacy feature" to [!NOTE] + "have significant limitations", since these fields are still actively processed without @deprecated markers
5. render-functions.md:166 — Expanded error key description to explain downstream consequence: value is treated as exception descriptor that can trigger raise_on_prerender_error
6. create-without-ssr.md:346 — Fixed outdated client registerServerComponent example from ({ rscPayloadGenerationUrlPath }, name) to (name) to match actual API at packages/react-on-rails-pro/src/registerServerComponent/client.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/pro/react-server-components/create-without-ssr.md (1)

362-363: ⚠️ Potential issue | 🟡 Minor

Remove or update outdated paragraph referencing rscPayloadGenerationUrlPath as an option.

This paragraph refers to rscPayloadGenerationUrlPath as an "option" and promises to explain it later, but:

  1. The updated API (line 346) no longer accepts an options object—it only accepts string component names.
  2. Based on the implementation, rscPayloadGenerationUrlPath comes from the railsContext object (injected by Rails via configuration), not from registerServerComponent.
  3. There is no further explanation of this "option" later in the document.

This text appears to be a holdover from the old API and should be removed or rewritten to clarify that rscPayloadGenerationUrlPath is configured via Rails (e.g., through the initializer or routes) and automatically provided to client components through the railsContext.

📝 Suggested fix: remove outdated paragraph
-The `rscPayloadGenerationUrlPath` option will be explained in detail later in this document. For now, just know that it specifies the base URL path for React Server Component requests.
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/pro/react-server-components/create-without-ssr.md` around lines 362 -
363, Remove the outdated paragraph that calls `rscPayloadGenerationUrlPath` an
"option" and promises later explanation; instead update the text to state that
`rscPayloadGenerationUrlPath` is provided via the Rails-injected `railsContext`
(configured in Rails initializers/routes) and is not an argument to
`registerServerComponent` (which now only accepts string component names), or
simply delete the paragraph if no replacement wording is desired.
🧹 Nitpick comments (1)
docs/oss/core-concepts/render-functions.md (1)

231-231: Tighten compound modifier hyphenation for readability.

“Client-side only rendering” reads better as “client-side-only rendering” in this bullet.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/core-concepts/render-functions.md` at line 231, The bullet text
"Client-side only rendering (always forces server rendering)" should be updated
to use tightened compound hyphenation—change the phrase to "client-side-only
rendering (always forces server rendering)" to improve readability; locate the
string in docs/oss/core-concepts/render-functions.md and replace the existing
phrase accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@docs/pro/react-server-components/create-without-ssr.md`:
- Around line 362-363: Remove the outdated paragraph that calls
`rscPayloadGenerationUrlPath` an "option" and promises later explanation;
instead update the text to state that `rscPayloadGenerationUrlPath` is provided
via the Rails-injected `railsContext` (configured in Rails initializers/routes)
and is not an argument to `registerServerComponent` (which now only accepts
string component names), or simply delete the paragraph if no replacement
wording is desired.

---

Nitpick comments:
In `@docs/oss/core-concepts/render-functions.md`:
- Line 231: The bullet text "Client-side only rendering (always forces server
rendering)" should be updated to use tightened compound hyphenation—change the
phrase to "client-side-only rendering (always forces server rendering)" to
improve readability; locate the string in
docs/oss/core-concepts/render-functions.md and replace the existing phrase
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 059e6268-9954-4a5d-bb75-a52482725a10

📥 Commits

Reviewing files that changed from the base of the PR and between ed159a9 and 3c427ba.

📒 Files selected for processing (4)
  • docs/oss/api-reference/javascript-api.md
  • docs/oss/building-features/react-router.md
  • docs/oss/core-concepts/render-functions.md
  • docs/pro/react-server-components/create-without-ssr.md
✅ Files skipped from review due to trivial changes (2)
  • docs/oss/building-features/react-router.md
  • docs/oss/api-reference/javascript-api.md

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c427baca2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/oss/core-concepts/render-functions.md Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 12, 2026

Review: docs: fix render function/helper API documentation

Overall this is a high-quality, well-researched documentation PR. I verified all the behavioral claims (parameter-count detection, prerender forcing, async/ExecJS behavior, error-key detection, clientProps merge, renderer-function error, registerServerComponent signatures) against the source code — they are all accurate.

One inaccuracy found

Compatibility matrix footnote (render-functions.md, line 255) — see inline comment.

The note claims ❌ combinations "silently produce incorrect output," giving react_component + hash → "JSON-stringifies the object" and react_component_hash + plain component → "returns empty/wrong values." The actual behavior in both cases is a hard raise ReactOnRails::Error, not a silent failure. The note should say these combinations raise at runtime so readers know they'll get a clear error, not mysterious wrong output.

Everything else looks correct

  • Parameter-count detection (0-1 / 2+ / 3) matches isRenderFunction.ts and ComponentRegistry.ts
  • react_component_hash forcing prerender: true confirmed at helper.rb:151
  • stream_react_component forcing prerender: true and dropping immediate_hydration with a warning confirmed in the Pro helper
  • Async + ExecJS returning '{}' confirmed at serverRenderReactComponent.ts:71-76
  • error key in isServerRenderHash confirmed at isServerRenderResult.ts:12
  • registerServerComponent client signature (...componentNames: string[]) confirmed in client.tsx:51
  • clientProps merge with symbol/string key coexistence confirmed in helper.rb:680-705
  • Renderer functions throwing during server render confirmed in serverRenderUtils.ts:32-34

The create-without-ssr.md fix for registerServerComponent('ReactServerComponentPage') (removing the stale object argument) is correct per the current client bundle signature.

@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed (2bef3c5)

I (Claude Code) addressed 2 remaining review comments, both verified against source:

  1. Promise streaming matrix entry (render-functions.md:252) — Changed stream_react_component + Promise from ❌ to ✅. Verified in streamingUtils.ts:234-245: the streaming code explicitly handles Promises that resolve to React elements (rejects hash shapes). Test suite confirms with asyncRenderFunction cases.

  2. ❌ footnote accuracy (render-functions.md:255) — The footnote incorrectly claimed ❌ means "silently produces incorrect output." Verified in helper.rb:104-110 and helper.rb:170-177: both mismatched combinations raise ReactOnRails::Error with descriptive messages. Updated footnote to reflect the actual error-raising behavior.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2bef3c5849

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/oss/core-concepts/render-functions.md Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 12, 2026

Review: docs: fix render function/helper API documentation

Overall this is a high-quality documentation PR that fills genuine gaps. I verified all the core technical claims against the source code — component detection logic, prerender forcing, ExecJS async behavior, clientProps merge, server render hash detection, and registerServerComponent signatures all check out. The compatibility matrix is accurate, and the legacy deprecation framing for redirectLocation/routeError is correct and helpful.

A couple of issues worth addressing before merge (see inline comments):

  1. Compatibility matrix footnote overstates the error type. The note says "❌ means the combination raises a ReactOnRails::Error at runtime" — but this is only accurate for the Ruby-side mismatches (react_component + hash, react_component_hash + string). For the renderer-function rows (where the error originates in JS from validateComponent) and the stream_react_component rows (Pro Node renderer errors), the propagated exception would be ReactOnRails::PrerenderError (if raise_on_prerender_error is enabled) or an error comment embedded in the HTML — not ReactOnRails::Error.

  2. react_component_hash also warns about immediate_hydration (verified at helper.rb:146-149) but the updated view-helpers-api.md docs for react_component_hash don't mention it. The PR adds this note only for stream_react_component.

Comment thread docs/oss/core-concepts/render-functions.md Outdated
Comment thread docs/oss/api-reference/view-helpers-api.md
…_hydration note

- Correct the `error` key description: it triggers server-render-hash detection
  only, not exception behavior (only `routeError` sets the error flag)
- Distinguish error types in compatibility matrix footnote: Ruby-side
  ReactOnRails::Error vs JS-side ReactOnRails::PrerenderError vs embedded HTML
- Add `immediate_hydration` deprecation note to react_component_hash docs

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@justin808
Copy link
Copy Markdown
Member Author

Review feedback addressed (489d433)

All 4 unresolved review threads have been addressed and resolved:

  1. error key behavior (render-functions.md:166) — Corrected: error is only used for server-render-hash detection, not as an exception descriptor. Only routeError sets the error flag.
  2. ❌ matrix footnote (render-functions.md:255) — Rewrote to distinguish Ruby-side ReactOnRails::Error, JS-side ReactOnRails::PrerenderError, and embedded error HTML output.
  3. immediate_hydration deprecation (view-helpers-api.md:60) — Added point 5 documenting that immediate_hydration is no longer supported for react_component_hash.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
docs/oss/core-concepts/render-functions.md (3)

166-167: Consider clarifying the error key gotcha.

The broadened server-render-hash detection is accurate, but the note "returning an object with an error key from a render function triggers server-render-hash processing" could surprise developers who use error as a regular data field in their component props. The current wording is clear about the detection logic, but you might consider adding a brief example or callout that this applies even when error is intended as component data (not a framework-level field).

However, since the text already states "This may be surprising if you intended error as a regular data field," the current wording is likely sufficient.

💡 Optional enhancement: add a concrete example

If you want to make the gotcha more concrete, you could add:

 5. **Server render result detection is broad** - React on Rails treats any object containing a `renderedHtml`, `redirectLocation`, `routeError`, or `error` key as a server render result (not a React component). This means returning an object with an `error` key from a render function triggers server-render-hash processing rather than being treated as a React component. Note that `error` is only used for detection — it is not itself treated as an exception descriptor. Only `routeError` sets the error flag during processing. This may be surprising if you intended `error` as a regular data field.
+
+   ```jsx
+   // ⚠️ This triggers server-render-hash processing, not component rendering
+   const MyComponent = (props) => ({ error: 'validation failed', data: null });
+   ```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/core-concepts/render-functions.md` around lines 166 - 167, Clarify
the "error" key gotcha by explicitly noting that any returned object containing
the key "error" (not just "routeError") will be treated as a server-render-hash
result and therefore won't be rendered as a React component; update the
paragraph to add one short concrete example reference (e.g., mention a component
like MyComponent that returns { error: 'validation failed' } as props) and/or a
one-sentence callout advising authors to avoid using a top-level "error" field
in render-returned objects (or rename it) to prevent accidental
server-render-hash handling — reference the terms "error", "routeError", and
"server-render-hash" so readers can map this guidance to the existing detection
logic.

136-138: Optional: vary sentence openings for style.

Three consecutive bullet points start with "For" (lines 136-138). While grammatically correct, varying the sentence structure could improve readability:

 > **Modern alternatives:**
 >
-> - For redirects during SSR, handle them in your Rails controller (e.g., check auth before rendering).
-> - For client-side redirects, use `<Navigate to="/path" />` (note: this is a [no-op during SSR](../building-features/react-router.md#navigate-component-ssr-behavior)).
-> - For route errors, use React Router's `errorElement` or an `ErrorBoundary`.
+ - Handle redirects during SSR in your Rails controller (e.g., check auth before rendering).
+ - For client-side redirects, use `<Navigate to="/path" />` (note: this is a [no-op during SSR](../building-features/react-router.md#navigate-component-ssr-behavior)).
+ - To handle route errors, use React Router's `errorElement` or an `ErrorBoundary`.

However, the current wording is clear and parallel, so this is purely stylistic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/core-concepts/render-functions.md` around lines 136 - 138, The three
bullets all begin with "For" which is repetitive; reword them to vary sentence
openings while preserving meaning and technical references: change the first to
start with an action like "Handle redirects during SSR in your Rails controller
(e.g., check auth before rendering)," the second to "Use <Navigate to=\"/path\"
/> for client-side redirects (note: this is a no-op during SSR)," and the third
to "Handle route errors with React Router's errorElement or an ErrorBoundary,"
keeping the parenthetical note about SSR behavior and the references to Rails
controller, <Navigate to="/path" />, errorElement, and ErrorBoundary.

231-231: Optional: hyphenate compound adjective.

"Client-side only rendering" should technically be hyphenated as "Client-side-only rendering" when the compound adjective modifies "rendering":

-- Client-side only rendering (always forces server rendering)
+- Client-side-only rendering (always forces server rendering)

This is a minor grammar nit and doesn't affect clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/core-concepts/render-functions.md` at line 231, Change the phrase
"Client-side only rendering" to the hyphenated compound adjective
"Client-side-only rendering" in the docs text so the compound properly modifies
"rendering" (update the line that currently reads exactly "Client-side only
rendering" in render-functions.md).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/oss/core-concepts/render-functions.md`:
- Around line 166-167: Clarify the "error" key gotcha by explicitly noting that
any returned object containing the key "error" (not just "routeError") will be
treated as a server-render-hash result and therefore won't be rendered as a
React component; update the paragraph to add one short concrete example
reference (e.g., mention a component like MyComponent that returns { error:
'validation failed' } as props) and/or a one-sentence callout advising authors
to avoid using a top-level "error" field in render-returned objects (or rename
it) to prevent accidental server-render-hash handling — reference the terms
"error", "routeError", and "server-render-hash" so readers can map this guidance
to the existing detection logic.
- Around line 136-138: The three bullets all begin with "For" which is
repetitive; reword them to vary sentence openings while preserving meaning and
technical references: change the first to start with an action like "Handle
redirects during SSR in your Rails controller (e.g., check auth before
rendering)," the second to "Use <Navigate to=\"/path\" /> for client-side
redirects (note: this is a no-op during SSR)," and the third to "Handle route
errors with React Router's errorElement or an ErrorBoundary," keeping the
parenthetical note about SSR behavior and the references to Rails controller,
<Navigate to="/path" />, errorElement, and ErrorBoundary.
- Line 231: Change the phrase "Client-side only rendering" to the hyphenated
compound adjective "Client-side-only rendering" in the docs text so the compound
properly modifies "rendering" (update the line that currently reads exactly
"Client-side only rendering" in render-functions.md).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9994e46a-55d7-4438-9f60-73aeb23b195e

📥 Commits

Reviewing files that changed from the base of the PR and between 2bef3c5 and 489d433.

📒 Files selected for processing (2)
  • docs/oss/api-reference/view-helpers-api.md
  • docs/oss/core-concepts/render-functions.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/oss/api-reference/view-helpers-api.md

Comment on lines +29 to +33
* - 0-1 params: Regular React component (function or class)
* - 2 params, or any function with `.renderFunction = true`: Render-Function — called with (props, railsContext),
* returns a React component, `{ renderedHtml }` object, or Promise (Pro Node renderer only)
* - 3 params: Renderer function — called with (props, railsContext, domNodeId),
* responsible for calling ReactDOM.render/hydrate directly (client-only)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter detection description has two inaccuracies that could mislead readers trying to understand how the registry works.

1. "2 params" should be "2 or more params"

ComponentRegistry.ts line 28 uses isRenderFunction(component) which checks component.length >= 2 (not exactly 2). A function with 4+ parameters is also detected as a render function. This matters for edge cases where someone wraps or decorates a function.

2. Renderer functions are a subtype of render functions, not a separate category

The three-bullet list implies mutual exclusivity between "Render-Function" (2 params) and "Renderer function" (3 params). In reality:

const renderFunction = isRenderFunction(component);          // true if length >= 2
const isRenderer = renderFunction && component.length === 3; // subset of render functions

A 3-param function satisfies both renderFunction === true AND isRenderer === true. The taxonomy is:

all registered components
  └─ render functions (length >= 2, or .renderFunction = true)
       └─ renderer functions (length === 3, subset of render functions)

Suggested correction:

Suggested change
* - 0-1 params: Regular React component (function or class)
* - 2 params, or any function with `.renderFunction = true`: Render-Function — called with (props, railsContext),
* returns a React component, `{ renderedHtml }` object, or Promise (Pro Node renderer only)
* - 3 params: Renderer function — called with (props, railsContext, domNodeId),
* responsible for calling ReactDOM.render/hydrate directly (client-only)
* Component detection: React on Rails distinguishes between component types by parameter count:
* - 0–1 params: Regular React component (function or class)
* - 2+ params, or any function with `.renderFunction = true`: Render-Function — called with (props, railsContext),
* returns a React component, `{ renderedHtml }` object, or Promise (Pro Node renderer only)
* - 3 params (a special case of Render-Function): Renderer function — called with (props, railsContext, domNodeId),
* responsible for calling ReactDOM.render/hydrate directly (client-only)

| Render function → Promise (compatible return shape) | ✅ (Pro Node renderer) | ✅ (Pro Node renderer, must resolve to hash with `componentHtml`) | ✅ (Pro Node renderer, must resolve to React element) |
| Renderer function (3 params) | ✅ (client-only) | ❌ | ❌ |

> **Note:** ❌ marks an unsupported combination. Some mismatches raise a `ReactOnRails::Error` directly in Ruby (e.g., `react_component` with a hash result raises `"Use react_component_hash (not react_component)..."`, and `react_component_hash` with a non-hash result raises `"Render-Function... expected to return an Object"`). Others (renderer functions used in server rendering, Pro Node renderer mismatches) throw a JavaScript error that becomes `ReactOnRails::PrerenderError` when `raise_on_prerender_error` is enabled, or is embedded as an error comment in the HTML when it is not. Either way, these combinations are not silent data failures — they will surface as errors or visible error output.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages quoted in this note don't quite match the source. The actual react_component error is:

Use react_component_hash (not react_component) to return a Hash to your ruby view code.

(helper.rb line 106)

And react_component_hash's error is:

Render-Function used by react_component_hash for #{component_name} is expected to return an Object.

(helper.rb line 172)

The note says "Render-Function... expected to return an Object" which is close but slightly paraphrased. Not a blocker, but worth tightening to the actual strings so readers can grep for them when debugging.

| Render function → `{ renderedHtml: string }` | ✅ | ❌ | ❌ |
| Render function → `{ renderedHtml: ReactElement }` | ✅ (prerender only) | ❌ | ❌ |
| Render function → `{ renderedHtml: { componentHtml, ... } }` | ❌ | ✅ | ❌ |
| Render function → Promise (compatible return shape) | ✅ (Pro Node renderer) | ✅ (Pro Node renderer, must resolve to hash with `componentHtml`) | ✅ (Pro Node renderer, must resolve to React element) |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The async Promise row and the non-async "Return Type 6" example (render-functions.md lines 363–388) use inconsistent return structures that may confuse readers:

  • Sync (Return Type 4): { renderedHtml: { componentHtml, title, ... } } — wrapped in renderedHtml
  • Async / Pro Node renderer (Return Type 6): { componentHtml, title, ... } — flat hash, no renderedHtml wrapper

The compatibility matrix note here says the Promise must "resolve to hash with componentHtml", which matches the flat-hash structure. But readers who switch from the sync to the async version will be confused about why the structure changes.

Consider adding a brief inline note to the async Promise row (or to section 6 example) explicitly calling out that the Pro Node renderer accepts the flat hash directly for backward compatibility, while the synchronous path requires the renderedHtml wrapper.

import registerServerComponent from 'react-on-rails-pro/registerServerComponent/client';

registerServerComponent({ rscPayloadGenerationUrlPath: 'rsc_payload/' }, 'ReactServerComponentPage');
registerServerComponent('ReactServerComponentPage');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix — the old example was broken. The registerServerComponent client implementation signature is (...componentNames: string[]) (rest parameters), so passing an object as the first argument was silently wrong. The corrected form is correct.

One small follow-up: the JSDoc comment in client.tsx lines 41–42 still mentions options.rscPayloadGenerationUrlPath as a documented parameter, but the function no longer accepts it. If that option was removed, the JSDoc should be cleaned up too (separate from this PR, but worth tracking).

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 12, 2026

Review

Verified all major behavioral claims against source code. The changes are well-researched and address real documentation gaps. A few issues to address before merging:

Must Fix

javascript-api.md lines 29–33 — parameter detection description is inaccurate (see inline comment)

The description implies "2 params → Render-Function" and "3 params → Renderer function" are mutually exclusive categories. They aren't:

  • The detection code uses component.length >= 2 (not exactly 2), so 4+-param functions are also render functions.
  • Renderer functions are a subset of render functions (isRenderer = renderFunction && component.length === 3), not a separate category.

This section will confuse anyone trying to understand why their 4-parameter function is or isn't detected correctly.

Suggestions

Async vs sync hash structure inconsistency — The sync return-type-4 example wraps the hash in renderedHtml: { componentHtml, ... }, but the async return-type-6 example returns a flat { componentHtml, ... }. The compatibility matrix note ("must resolve to hash with componentHtml") implies the flat structure is correct for the async Pro Node renderer path, but the asymmetry is unexplained. A brief note would prevent confusion.

Error message strings — The compatibility matrix footnote paraphrases two runtime error messages slightly. Worth tightening them to the verbatim strings so readers can grep for them when debugging (see inline comment on line 255 of render-functions.md).

Verified Accurate

The following claims were verified against source code and are correct:

Claim Source
react_component_hash forces prerender: true silently (no warning logged) helper.rb:151 — direct assignment, no conditional warning
stream_react_component forces prerender: true and warns on immediate_hydration react_on_rails_pro_helper.rb:127–134
error key in return value triggers server-render-hash detection isServerRenderResult.ts:3–14 — all four keys checked
clientProps symbol/string key merge logic helper.rb:680–705client_prop_target_key handles coexistence correctly
react_component raises when given a hash result, react_component_hash raises when given a non-hash helper.rb:104–110, helper.rb:170–179
registerServerComponent client signature is (...componentNames: string[]) client.tsx:51 — rest params, no options object
<Navigate> is a no-op during SSR Accurate per React Router's useEffect-based implementation

Overall this is a solid improvement to some of the most confusing parts of the API documentation.

@justin808 justin808 merged commit 63c4cfe into main Apr 12, 2026
27 checks passed
@justin808 justin808 deleted the jg/2911-docs-render-api branch April 12, 2026 23:39
justin808 added a commit that referenced this pull request Apr 18, 2026
…ages

* origin/main:
  Fix initial page startup race for late-loading client bundles (#3151)
  chore: apply prettier formatting to tracked docs files (#3153)
  docs: comprehensive RSC API documentation and registration consolidation (#3140)
  Split rspec-package-tests into parallel generator/unit shards (#3134)
  fix: add concurrency groups to long-running CI workflows (#3133)
  refactor: add RenderRequest, JsCodeBuilder, and RenderingStrategy abstractions (#3094)
  fix: address deferred review items from PR #2849 (#3093)
  Add complimentary OSS license policy for React on Rails Pro (#3123)
  fix: centralize CI docs-only detection and add CLI flag validation (#3091)
  refactor: replace stub-throw + Object.assign with capability-based composition (#3096)
  Enhance address-review with parallel fixes, self-review, and Greptile verification (#3121)
  fix: Doctor no longer fails custom projects for missing bin/dev (#3117)
  fix: cap webpack <5.106.0 to prevent ExecJS SSR breakage (#3095)
  Add Rspack + RSC compatibility tests and documentation (#1828) (#3120)
  Add error scenarios hub and test pages (#2497)
  docs: document polyfill requirements for web-targeted server bundles (#3092)
  docs: RSC integration pitfalls from tutorial app (#3087)
  docs: fix render function/helper API documentation (#3088)
  Doctor: accept TS/TSX server bundle suffixes (#3111)
  feat: add CI guard requiring sidebar updates when adding docs (#3089)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review and fix docs for render functions, renderer functions, react_component_hash, registerServerComponent, and wrapServerComponentRenderer

1 participant