Skip to content

Commit 36c4c61

Browse files
committed
should force load react-components which send over turbo-stream
1 parent 36f342c commit 36c4c61

File tree

17 files changed

+129
-3
lines changed

17 files changed

+129
-3
lines changed

Gemfile.development_dependencies

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ gem "sprockets", "~> 4.0"
2222

2323
gem "amazing_print"
2424

25+
gem "turbo-rails"
26+
2527
group :development, :test do
2628
gem "listen"
2729
gem "pry"

lib/react_on_rails/configuration.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ def self.configuration
3939
i18n_output_format: nil,
4040
components_subdirectory: nil,
4141
make_generated_server_bundle_the_entrypoint: false,
42-
defer_generated_component_packs: true
42+
defer_generated_component_packs: true,
43+
# forces the loading of React components
44+
force_load: false
4345
)
4446
end
4547

@@ -53,7 +55,8 @@ class Configuration
5355
:server_render_method, :random_dom_id, :auto_load_bundle,
5456
:same_bundle_for_client_and_server, :rendering_props_extension,
5557
:make_generated_server_bundle_the_entrypoint,
56-
:defer_generated_component_packs
58+
:defer_generated_component_packs,
59+
:force_load
5760

5861
# rubocop:disable Metrics/AbcSize
5962
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
@@ -68,7 +71,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
6871
same_bundle_for_client_and_server: nil,
6972
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
7073
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
71-
components_subdirectory: nil, auto_load_bundle: nil)
74+
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil)
7275
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
7376
self.generated_assets_dirs = generated_assets_dirs
7477
self.generated_assets_dir = generated_assets_dir
@@ -106,6 +109,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
106109
self.auto_load_bundle = auto_load_bundle
107110
self.make_generated_server_bundle_the_entrypoint = make_generated_server_bundle_the_entrypoint
108111
self.defer_generated_component_packs = defer_generated_component_packs
112+
self.force_load = force_load
109113
end
110114
# rubocop:enable Metrics/AbcSize
111115

lib/react_on_rails/helper.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,14 @@ def internal_react_component(react_component_name, options = {})
441441
"data-trace" => (render_options.trace ? true : nil),
442442
"data-dom-id" => render_options.dom_id)
443443

444+
if render_options.force_load
445+
component_specification_tag.concat(
446+
content_tag(:script, %(
447+
ReactOnRails.reactOnRailsComponentLoaded('#{render_options.dom_id}');
448+
).html_safe)
449+
)
450+
end
451+
444452
load_pack_for_generated_component(react_component_name, render_options)
445453
# Create the HTML rendering part
446454
result = server_rendered_react_component(render_options)

lib/react_on_rails/react_component/render_options.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ def logging_on_server
9191
retrieve_configuration_value_for(:logging_on_server)
9292
end
9393

94+
def force_load
95+
retrieve_configuration_value_for(:force_load)
96+
end
97+
9498
def to_s
9599
"{ react_component_name = #{react_component_name}, options = #{options}, request_digest = #{request_digest}"
96100
end

node_package/src/ReactOnRails.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ ctx.ReactOnRails = {
133133
ClientStartup.reactOnRailsPageLoaded();
134134
},
135135

136+
reactOnRailsComponentLoaded(domId: string): void {
137+
ClientStartup.reactOnRailsComponentLoaded(domId);
138+
},
139+
136140
/**
137141
* Returns CSRF authenticity token inserted by Rails csrf_meta_tags
138142
* @returns String or null

node_package/src/clientStartup.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,25 @@ export function reactOnRailsPageLoaded(): void {
218218
forEachReactOnRailsComponentRender(context, railsContext);
219219
}
220220

221+
export function reactOnRailsComponentLoaded(domId: string): void {
222+
debugTurbolinks(`reactOnRailsComponentLoaded ${domId}`);
223+
224+
const railsContext = parseRailsContext();
225+
226+
// If no react on rails components
227+
if (!railsContext) return;
228+
229+
const context = findContext();
230+
if (supportsRootApi) {
231+
context.roots = [];
232+
}
233+
234+
const el = document.querySelector(`[data-dom-id=${domId}]`);
235+
if (!el) return;
236+
237+
render(el, context, railsContext);
238+
}
239+
221240
function unmount(el: Element): void {
222241
const domNodeId = domNodeIdForEl(el);
223242
const domNode = document.getElementById(domNodeId);

node_package/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export interface ReactOnRails {
126126
setOptions(newOptions: {traceTurbolinks: boolean}): void;
127127
reactHydrateOrRender(domNode: Element, reactElement: ReactElement, hydrate: boolean): RenderReturnType;
128128
reactOnRailsPageLoaded(): void;
129+
reactOnRailsComponentLoaded(domId: string): void;
129130
authenticityToken(): string | null;
130131
authenticityHeaders(otherHeaders: { [id: string]: string }): AuthenticityHeaders;
131132
option(key: string): string | number | boolean | undefined;

spec/dummy/app/controllers/pages_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ def data
3636
}.merge(xss_payload)
3737
}
3838

39+
@app_props_hello_from_turbo_stream = {
40+
helloTurboStreamData: {
41+
name: "Mrs. Client Side Rendering From Turbo Stream"
42+
}.merge(xss_payload)
43+
}
44+
3945
@app_props_hello_again = {
4046
helloWorldData: {
4147
name: "Mrs. Client Side Hello Again"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<%= turbo_frame_tag 'hello-turbo-stream' do %>
2+
<%= button_to "send me hello-turbo-stream component", turbo_stream_send_hello_world_path %>
3+
<% end %>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<%= turbo_stream.update 'hello-turbo-stream' do %>
2+
<%= react_component("HelloTurboStream", props: @app_props_hello_from_turbo_stream, force_load: true) %>
3+
<% end %>

0 commit comments

Comments
 (0)