Skip to content

Conversation

AbanoubGhadban
Copy link
Collaborator

@AbanoubGhadban AbanoubGhadban commented Sep 26, 2025

Summary by CodeRabbit

  • New Features

    • Added two demo pages showcasing async server render functions that return either a string or a React component.
    • Integrated these pages into the app navigation for easy access.
    • Pages support prerendering and tracing and display echoed props for clarity.
  • Tests

    • Added system tests to validate rendering, props display, and server logs for both new demo pages.

This change is Reviewable

AbanoubGhadban and others added 2 commits September 26, 2025 15:15
make renderer runnable on one process Modify example views to pass props to components and add integration tests for async rendering functionality. Revert "make renderer runnable on one process" This reverts commit 91efa37a665f836b05a116e6548ef809d956a67c. Update Gemfile and package.json to use the master branch of react_on_rails Update component source paths and improve menu link labels for clarity revert changes to react on rails dependency
Copy link
Contributor

coderabbitai bot commented Sep 26, 2025

Walkthrough

Adds two demo pages, routes, components, and tests to showcase async server render functions in React on Rails that either return an HTML string or a React component. Includes client and server files for each example, menu links, and system specs validating server-rendered output and logs.

Changes

Cohort / File(s) Summary
Views: async demo pages
react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_component.html.erb, react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_string.html.erb
New pages rendering examples via react_component with props { hello: "world" }, prerender: true, and tracing enabled. Each includes details linking to its server component source.
Shared menu updates
react_on_rails_pro/spec/dummy/app/views/shared/_menu.erb
Adds two menu links to the new async demo pages.
Routes
react_on_rails_pro/spec/dummy/config/routes.rb
Adds GET routes for /async_render_function_returns_string and /async_render_function_returns_component mapped to pages#....
Client components
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx, react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
New client components exporting simple wrappers that render EchoProps with forwarded props.
Server render functions
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx, react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
New async default exports: one returns a React component that renders EchoProps; the other returns an HTML string via renderToString(<EchoProps .../>).
System tests
react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
Adds system specs visiting the two pages, asserting rendered props and server-render log output.

Sequence Diagram(s)

sequenceDiagram autonumber actor U as User Browser participant R as Rails (Pages#async_render_function_returns_string) participant V as View (.erb) participant RoR as ReactOnRails (SSR) participant RF as Async Render Function (returns string) participant RDS as ReactDOMServer U->>R: GET /async_render_function_returns_string R->>V: Render view V->>RoR: react_component(..., prerender: true) RoR->>RF: Call async render(props, railsContext) RF->>RDS: renderToString(<EchoProps {...props} />) RDS-->>RF: HTML string RF-->>RoR: Promise resolves to HTML string RoR-->>V: Inject server HTML V-->>U: Response with SSR HTML note over U,RoR: Client hydration occurs after load 
Loading
sequenceDiagram autonumber actor U as User Browser participant R as Rails (Pages#async_render_function_returns_component) participant V as View (.erb) participant RoR as ReactOnRails (SSR) participant RF as Async Render Function (returns component) U->>R: GET /async_render_function_returns_component R->>V: Render view V->>RoR: react_component(..., prerender: true) RoR->>RF: Call async render(props, railsContext) RF-->>RoR: Promise resolves to React component RoR->>RoR: SSR render of returned component RoR-->>V: Inject server HTML V-->>U: Response with SSR HTML note over U,RoR: Client hydration follows 
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • justin808
  • Judahmeek
  • alexeyr-ci

Poem

New routes hop in, two pages alight,
Async dreams render string or sprite.
Echoed props in moonlit logs,
Tests nibble bugs like savvy hogs.
I thump the ground—deploy delight!
🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely indicates the addition of an example for returning a component from an async render function, accurately reflecting a primary change in the pull request. It is clear, specific, and does not include unnecessary details or vague terms.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch abanoubghadban/ror1719/add-example-for-returning-component-from-async-render-function

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.

Copy link

claude bot commented Sep 26, 2025

Code Review

Thank you for adding examples for async render functions. This demonstrates both patterns well (returning components and strings).

Strengths

  • Good test coverage verifying server-side rendering output
  • Clear separation with client/server files following existing patterns
  • Navigation items added appropriately

Issues to Address

  1. Misleading Comments: Server files contain 'Top level component for simple client side only rendering' which is incorrect for server-side components

  2. Unnecessary 'use client' Directive: Server components shouldn't have 'use client' directives

  3. Code Duplication: Client components are identical - consider sharing

  4. Missing Error Handling: Add try-catch blocks for production readiness

  5. Documentation: 'fictional example' comment could explain real use cases better

Performance

  • The artificial await Promise.resolve() in AsyncRenderFunctionReturnsComponent.server.jsx serves no purpose

Security

No issues found - props handled safely

Style

Per CLAUDE.md: Ensure newlines at file ends and run bundle exec rubocop

Good addition overall - addressing these points would make it excellent.

Copy link
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: 0

🧹 Nitpick comments (2)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (1)

1-17: Drop 'use client' in server render-function and fix misleading comment; optionally name returned component.
The server file shouldn’t advertise client-only rendering; naming the returned component improves DevTools traces.

Apply:

-'use client'; - -// Top level component for simple client side only rendering +// Server render-function that resolves to a React component import React from 'react'; import EchoProps from '../components/EchoProps'; @@ export default async (props, _railsContext) => { await Promise.resolve(); - return () => <EchoProps {...props} />; + return function AsyncReturnsComponentInner() { + return <EchoProps {...props} />; + }; };
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx (1)

1-4: Drop the 'use client' directive from this server render example

This module is meant to run on the server bundle, so marking it as a client component is misleading and risks confusing toolchains that honor the directive (and might try to tree-shake it into the client build). Let’s remove the directive and update the comment to describe the async server render use case instead.

-'use client'; - -// Top level component for simple client side only rendering +// Async server render function returning an HTML string example
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbbb8fc and 2a5c2c1.

📒 Files selected for processing (9)
  • react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_component.html.erb (1 hunks)
  • react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_string.html.erb (1 hunks)
  • react_on_rails_pro/spec/dummy/app/views/shared/_menu.erb (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/config/routes.rb (1 hunks)
  • react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
{Gemfile,Rakefile,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,**/*.{rb,rake,gemspec,ru}}: Before every commit/push, run bundle exec rubocop and fix all violations in Ruby code
Let RuboCop handle all Ruby code formatting; never manually format Ruby files

Files:

  • react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
  • react_on_rails_pro/spec/dummy/config/routes.rb
{Gemfile,Rakefile,**/*.{rb,rake,gemspec,ru,js,jsx,ts,tsx,json,yml,yaml,md,css,scss}}

📄 CodeRabbit inference engine (CLAUDE.md)

Ensure all committed files end with a trailing newline character

Files:

  • react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/config/routes.rb
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint for JavaScript/TypeScript and fix all linter offenses before committing

Files:

  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
**/*.{js,jsx,ts,tsx,json,yml,yaml,md,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Let Prettier handle all non-Ruby file formatting; never manually format these files

Files:

  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
🧠 Learnings (3)
📚 Learning: 2024-07-27T10:08:35.868Z
Learnt from: theforestvn88 PR: shakacode/react_on_rails#1620 File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3 Timestamp: 2024-07-27T10:08:35.868Z Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88. 

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
📚 Learning: 2025-02-13T16:50:47.848Z
Learnt from: AbanoubGhadban PR: shakacode/react_on_rails#1644 File: node_package/src/clientStartup.ts:18-21 Timestamp: 2025-02-13T16:50:47.848Z Learning: In the react_on_rails module, the `reactOnRailsPageUnloaded` function in clientStartup.ts is intentionally kept private as it's only used internally as a callback for `onPageUnloaded`. 

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban PR: shakacode/react_on_rails#1745 File: node_package/src/RSCRequestTracker.ts:8-14 Timestamp: 2025-07-08T05:57:29.630Z Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime. 

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx
🧬 Code graph analysis (4)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx (3)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx (1)
  • props (8-8)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (1)
  • props (14-17)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx (1)
  • props (17-20)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx (2)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (1)
  • props (14-17)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx (1)
  • props (8-8)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (2)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx (1)
  • props (8-8)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx (1)
  • props (17-20)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.server.jsx (3)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.server.jsx (1)
  • props (14-17)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ConsoleLogsInAsyncServer.server.jsx (1)
  • _railsContext (7-39)
node_package/src/ReactDOMServer.cts (1)
  • renderToString (4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: dummy-app-integration-tests (3.4, 22)
  • GitHub Check: dummy-app-integration-tests (3.2, 20)
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: claude-review
  • GitHub Check: build
  • GitHub Check: build-and-test
🔇 Additional comments (7)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsComponent.client.jsx (1)

8-8: LGTM, mirrors the string example and keeps props forwarding simple.
Consistent with other client examples.

react_on_rails_pro/spec/dummy/app/views/shared/_menu.erb (1)

58-63: Menu entries wired correctly to new routes.
Helpers exist and placement matches nearby examples.

react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_component.html.erb (1)

6-6: LGTM: Proper react_component invocation with prerender and trace.
Matches the server render-function returning a component.

react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb (1)

220-240: Solid coverage for both async-return variants.
Assertions mirror existing patterns and should be stable.

react_on_rails_pro/spec/dummy/app/views/pages/async_render_function_returns_string.html.erb (1)

6-6: LGTM: Invokes the string-returning render-function with prerender + trace.
Consistent with component-return example.

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/AsyncRenderFunctionReturnsString.client.jsx (1)

8-8: LGTM, consistent with other client-only examples.
Simple props echo for parity with server example.

react_on_rails_pro/spec/dummy/config/routes.rb (1)

37-38: Routes look good.
REST helpers are generated; no conflicts with existing routes.

@AbanoubGhadban AbanoubGhadban merged commit 04f3d35 into master Sep 26, 2025
17 of 18 checks passed
@AbanoubGhadban AbanoubGhadban deleted the abanoubghadban/ror1719/add-example-for-returning-component-from-async-render-function branch September 26, 2025 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant