Skip to content

Commit b7f640b

Browse files
Add async components demo with concurrent rendering example
1 parent 5d78a83 commit b7f640b

File tree

5 files changed

+77
-0
lines changed

5 files changed

+77
-0
lines changed

react_on_rails_pro/spec/dummy/app/controllers/pages_controller.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
class PagesController < ApplicationController # rubocop:disable Metrics/ClassLength
44
include ReactOnRailsPro::RSCPayloadRenderer
55
include RscPostsPageOverRedisHelper
6+
include ReactOnRailsPro::AsyncRendering
7+
8+
enable_async_react_rendering only: [:async_components_demo]
69

710
XSS_PAYLOAD = { "<script>window.alert('xss1');</script>" => '<script>window.alert("xss2");</script>' }.freeze
811
PROPS_NAME = "Mr. Server Side Rendering"
@@ -157,6 +160,12 @@ def console_logs_in_async_server
157160
render "/pages/pro/console_logs_in_async_server"
158161
end
159162

163+
# Demo page showing 10 async components rendering concurrently
164+
# Each component delays 1 second - sequential would take ~10s, concurrent takes ~1s
165+
def async_components_demo
166+
render "/pages/pro/async_components_demo"
167+
end
168+
160169
# See files in spec/dummy/app/views/pages
161170

162171
helper_method :calc_slow_app_props_server_render
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<h1>Async React Components Demo</h1>
2+
<p>
3+
This page renders 10 React components, each with a 1-second delay.
4+
<br>
5+
<strong>Sequential rendering:</strong> ~10 seconds
6+
<br>
7+
<strong>Concurrent rendering (async_react_component):</strong> ~1 second
8+
</p>
9+
10+
<% start_time = Time.now %>
11+
12+
<%
13+
# Start all 10 async renders immediately (non-blocking)
14+
components = 10.times.map do |i|
15+
async_react_component(
16+
"DelayedComponent",
17+
props: { index: i + 1, delayMs: 1000 },
18+
prerender: true
19+
)
20+
end
21+
%>
22+
23+
<div id="components-container">
24+
<% components.each do |component| %>
25+
<%= component.value %>
26+
<% end %>
27+
</div>
28+
29+
<% elapsed = Time.now - start_time %>
30+
<p>
31+
<strong>Total render time:</strong> <%= (elapsed * 1000).round %>ms
32+
<br>
33+
<em>If this is close to 1 second instead of 10 seconds, concurrent rendering is working!</em>
34+
</p>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use client';
2+
3+
import React from 'react';
4+
5+
// Client-side version of DelayedComponent (no delay needed on client)
6+
const DelayedComponent = ({ index, delayMs = 1000 }) => (
7+
<div style={{ padding: '10px', margin: '5px', border: '1px solid #ccc' }}>
8+
<strong>Component {index}</strong> - Rendered after {delayMs}ms delay
9+
</div>
10+
);
11+
12+
export default DelayedComponent;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use client';
2+
3+
import React from 'react';
4+
5+
// Component that simulates a slow render by delaying for 1 second
6+
// Used to demonstrate concurrent rendering with async_react_component
7+
const DelayedComponent = ({ index, delayMs = 1000 }) => (
8+
<div style={{ padding: '10px', margin: '5px', border: '1px solid #ccc' }}>
9+
<strong>Component {index}</strong> - Rendered after {delayMs}ms delay
10+
</div>
11+
);
12+
13+
// Async render function that delays for specified time before returning
14+
export default async (props, _railsContext) => {
15+
const { delayMs = 1000 } = props;
16+
17+
// Simulate slow server-side data fetching
18+
await new Promise((resolve) => setTimeout(resolve, delayMs));
19+
20+
return () => <DelayedComponent {...props} />;
21+
};

react_on_rails_pro/spec/dummy/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
get "server_router_client_render/(*all)" => "pages#server_router_client_render", as: :server_router_client_render
3939
get "async_render_function_returns_string" => "pages#async_render_function_returns_string"
4040
get "async_render_function_returns_component" => "pages#async_render_function_returns_component"
41+
get "async_components_demo" => "pages#async_components_demo", as: :async_components_demo
4142
rsc_payload_route controller: "pages"
4243

4344
# routes copied over from react on rails

0 commit comments

Comments
 (0)