Module: ReactOnRailsProHelper

Includes:
ScoutApm::Tracer
Defined in:
app/helpers/react_on_rails_pro_helper.rb

Overview

rubocop:disable Metrics/ModuleLength

Instance Method Summary collapse

Instance Method Details

#cached_react_component(component_name, raw_options = {}, &block) ⇒ Object

Provide caching support for react_component in a manner akin to Rails fragment caching. All the same options as react_component apply with the following difference:

  1. You must pass the props as a block. This is so that the evaluation of the props is not done if the cache can be used.

  2. Provide the cache_key option cache_key: String or Array (or Proc returning a String or Array) containing your cache keys. If prerender is set to true, the server bundle digest will be included in the cache key. The cache_key value is the same as used for conventional Rails fragment caching.

  3. Optionally provide the ‘:cache_options` key with a value of a hash including as :compress, :expires_in, :race_condition_ttl as documented in the Rails Guides

  4. Provide boolean values for ‘:if` or `:unless` to conditionally use caching.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'app/helpers/react_on_rails_pro_helper.rb', line 51

def cached_react_component(component_name, raw_options = {}, &block)
  ReactOnRailsPro::Utils.with_trace(component_name) do
    check_caching_options!(raw_options, block)

    fetch_react_component(component_name, raw_options) do
      sanitized_options = raw_options
      sanitized_options[:props] = yield
      sanitized_options[:skip_prerender_cache] = true
      sanitized_options[:auto_load_bundle] =
        ReactOnRails.configuration.auto_load_bundle || raw_options[:auto_load_bundle]
      react_component(component_name, sanitized_options)
    end
  end
end

#cached_react_component_hash(component_name, raw_options = {}, &block) ⇒ Object

Provide caching support for react_component_hash in a manner akin to Rails fragment caching. All the same options as react_component_hash apply with the following difference:

  1. You must pass the props as a block. This is so that the evaluation of the props is not done if the cache can be used.

  2. Provide the cache_key option cache_key: String or Array (or Proc returning a String or Array) containing your cache keys. Since prerender is automatically set to true, the server bundle digest will be included in the cache key. The cache_key value is the same as used for conventional Rails fragment caching.

  3. Optionally provide the ‘:cache_options` key with a value of a hash including as :compress, :expires_in, :race_condition_ttl as documented in the Rails Guides

  4. Provide boolean values for ‘:if` or `:unless` to conditionally use caching.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/helpers/react_on_rails_pro_helper.rb', line 78

def cached_react_component_hash(component_name, raw_options = {}, &block)
  raw_options[:prerender] = true

  ReactOnRailsPro::Utils.with_trace(component_name) do
    check_caching_options!(raw_options, block)

    fetch_react_component(component_name, raw_options) do
      sanitized_options = raw_options
      sanitized_options[:props] = yield
      sanitized_options[:skip_prerender_cache] = true
      sanitized_options[:auto_load_bundle] =
        ReactOnRails.configuration.auto_load_bundle || raw_options[:auto_load_bundle]
      react_component_hash(component_name, sanitized_options)
    end
  end
end

#cached_stream_react_component(component_name, raw_options = {}, &block) ⇒ Object

Provide caching support for stream_react_component in a manner akin to Rails fragment caching. All the same options as stream_react_component apply with the following differences:

  1. You must pass the props as a block. This is so that the evaluation of the props is not done if the cache can be used.

  2. Provide the cache_key option cache_key: String or Array (or Proc returning a String or Array) containing your cache keys. Since prerender is automatically set to true, the server bundle digest will be included in the cache key. The cache_key value is the same as used for conventional Rails fragment caching.

  3. Optionally provide the ‘:cache_options` key with a value of a hash including as :compress, :expires_in, :race_condition_ttl as documented in the Rails Guides

  4. Provide boolean values for ‘:if` or `:unless` to conditionally use caching.



205
206
207
208
209
210
# File 'app/helpers/react_on_rails_pro_helper.rb', line 205

def cached_stream_react_component(component_name, raw_options = {}, &block)
  ReactOnRailsPro::Utils.with_trace(component_name) do
    check_caching_options!(raw_options, block)
    fetch_stream_react_component(component_name, raw_options, &block)
  end
end

#fetch_react_component(component_name, options) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'app/helpers/react_on_rails_pro_helper.rb', line 11

def fetch_react_component(component_name, options)
  if ReactOnRailsPro::Cache.use_cache?(options)
    cache_key = ReactOnRailsPro::Cache.react_component_cache_key(component_name, options)
    Rails.logger.debug { "React on Rails Pro cache_key is #{cache_key.inspect}" }
    cache_options = options[:cache_options]
    cache_hit = true
    result = Rails.cache.fetch(cache_key, cache_options) do
      cache_hit = false
      yield
    end
    if cache_hit
      render_options = ReactOnRails::ReactComponent::RenderOptions.new(
        react_component_name: component_name,
        options: options
      )
      load_pack_for_generated_component(component_name, render_options)
    end
    # Pass back the cache key in the results only if the result is a Hash
    if result.is_a?(Hash)
      result[:RORP_CACHE_KEY] = cache_key
      result[:RORP_CACHE_HIT] = cache_hit
    end
    result
  else
    yield
  end
end

#rsc_payload_react_component(component_name, options = {}) ⇒ String

Note:

This helper requires React Server Components support to be enabled in your configuration: ReactOnRailsPro.configure do |config|

config.enable_rsc_support = true

end

Note:

You don’t have to deal directly with this helper function - it’s used internally by the

Renders the React Server Component (RSC) payload for a given component. This helper generates a special format designed by React for serializing server components and transmitting them to the client.

Example NDJSON stream:

{"html":"<RSC Payload>","consoleReplayScript":"","hasErrors":false,"isShellReady":true}
{"html":"<RSC Payload>","consoleReplayScript":"console.log('Loading...')","hasErrors":false,"isShellReady":true}

The RSC payload within the html field contains:

  • The component’s rendered output from the server

  • References to client components that need hydration

  • Data props passed to client components

‘rsc_payload_route` helper function. The returned data from this function is used internally by components registered using the `registerServerComponent` function. Don’t use it unless you need more control over the RSC payload generation. To know more about RSC payload, see the following link:

Examples:

Basic usage with a server component

<%= rsc_payload_react_component("ReactServerComponentPage") %>

With props and tracing enabled

<%= rsc_payload_react_component("RSCPostsPage",
      props: { artificialDelay: 1000 },
      trace: true) %>

Parameters:

  • component_name (String)

    The name of the React component to render. This component should be a server component or a mixed component tree containing both server and client components.

  • options (Hash) (defaults to: {})

    Options for rendering the component

Options Hash (options):

  • :props (Hash)

    Props to pass to the component (default: {})

  • :trace (Boolean)

    Enable tracing for debugging (default: false)

  • :id (String)

    Custom DOM ID for the component container (optional)

Returns:

  • (String)

    Returns a Newline Delimited JSON (NDJSON) stream where each line contains a JSON object with:

    • html: The RSC payload containing the rendered server components and client component references

    • consoleReplayScript: JavaScript to replay server-side console logs in the client

    • hasErrors: Boolean indicating if any errors occurred during rendering

    • isShellReady: Boolean indicating if the initial shell is ready for hydration

Raises:

See Also:



184
185
186
187
188
189
190
191
# File 'app/helpers/react_on_rails_pro_helper.rb', line 184

def rsc_payload_react_component(component_name, options = {})
  # rsc_payload_react_component doesn't have the prerender option
  # Because setting prerender to false will not do anything
  options[:prerender] = true
  run_stream_inside_fiber do
    internal_rsc_payload_react_component(component_name, options)
  end
end

#stream_react_component(component_name, options = {}) ⇒ Object

Streams a server-side rendered React component using React’s ‘renderToPipeableStream`. Supports React 18 features like Suspense, concurrent rendering, and selective hydration. Enables progressive rendering and improved performance for large components.

Note: This function can only be used with React on Rails Pro. The view that uses this function must be rendered using the ‘stream_view_containing_react_components` method from the React on Rails Pro gem.

Example of an async React component that can benefit from streaming:

const AsyncComponent = async () =>

const data = await fetchData();
return <div>{data</div>;

};

function App() {

return (
  <Suspense fallback={<div>Loading...</div>}>
    <AsyncComponent />
  </Suspense>
);

}

Any other options are passed to the content tag, including the id.

Parameters:

  • component_name (String)

    Name of your registered component

  • options (Hash) (defaults to: {})

    Options for rendering

Options Hash (options):

  • :props (Hash)

    Props to pass to the react component

  • :dom_id (String)

    DOM ID of the component container

  • :html_options (Hash)

    Options passed to content_tag

  • :trace (Boolean)

    Set to true to add extra debugging information to the HTML

  • :raise_on_prerender_error (Boolean)

    Set to true to raise exceptions during server-side rendering



126
127
128
129
130
131
132
133
134
# File 'app/helpers/react_on_rails_pro_helper.rb', line 126

def stream_react_component(component_name, options = {})
  # stream_react_component doesn't have the prerender option
  # Because setting prerender to false is equivalent to calling react_component with prerender: false
  options[:prerender] = true
  options = options.merge(immediate_hydration: true) unless options.key?(:immediate_hydration)
  run_stream_inside_fiber do
    internal_stream_react_component(component_name, options)
  end
end