Module: ReactOnRailsProHelper
- Includes:
- ScoutApm::Tracer
- Defined in:
- app/helpers/react_on_rails_pro_helper.rb
Overview
rubocop:disable Metrics/ModuleLength
Instance Method Summary collapse
-
#async_react_component(component_name, options = {}) ⇒ ReactOnRailsPro::AsyncValue
Renders a React component asynchronously, returning an AsyncValue immediately.
-
#cached_async_react_component(component_name, raw_options = {}) { ... } ⇒ ReactOnRailsPro::AsyncValue, ReactOnRailsPro::ImmediateAsyncValue
Renders a React component asynchronously with caching support.
-
#cached_react_component(component_name, raw_options = {}, &block) ⇒ Object
Provide caching support for react_component in a manner akin to Rails fragment caching.
-
#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.
-
#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.
- #fetch_react_component(component_name, options) ⇒ Object
-
#rsc_payload_react_component(component_name, options = {}) ⇒ String
Renders the React Server Component (RSC) payload for a given component.
- #rsc_payload_react_component_with_async_props(component_name, options = {}, &props_block) ⇒ Object
-
#stream_react_component(component_name, options = {}) ⇒ Object
Streams a server-side rendered React component using React’s ‘renderToPipeableStream`.
- #stream_react_component_with_async_props(component_name, options = {}, &props_block) ⇒ Object
Instance Method Details
#async_react_component(component_name, options = {}) ⇒ ReactOnRailsPro::AsyncValue
Renders a React component asynchronously, returning an AsyncValue immediately. Multiple async_react_component calls will execute their HTTP rendering requests concurrently instead of sequentially.
Requires the controller to include ReactOnRailsPro::AsyncRendering and call enable_async_react_rendering.
297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 297 def async_react_component(component_name, = {}) unless defined?(@react_on_rails_async_barrier) && @react_on_rails_async_barrier raise ReactOnRailsPro::Error, "async_react_component requires AsyncRendering concern. " \ "Include ReactOnRailsPro::AsyncRendering in your controller and call enable_async_react_rendering." end task = @react_on_rails_async_barrier.async do react_component(component_name, ) end ReactOnRailsPro::AsyncValue.new(task:) end |
#cached_async_react_component(component_name, raw_options = {}) { ... } ⇒ ReactOnRailsPro::AsyncValue, ReactOnRailsPro::ImmediateAsyncValue
Renders a React component asynchronously with caching support. Cache lookup is synchronous - cache hits return immediately without async. Cache misses trigger async render and cache the result on completion.
All the same options as cached_react_component apply:
-
You must pass the props as a block (evaluated only on cache miss)
-
Provide the cache_key option
-
Optionally provide :cache_options for Rails.cache (expires_in, etc.)
-
Provide :if or :unless for conditional caching
-
Optionally provide :cache_tags for revalidation via ReactOnRailsPro.revalidate_tag
331 332 333 334 335 336 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 331 def cached_async_react_component(component_name, = {}, &block) ReactOnRailsPro::Utils.with_trace(component_name) do (, block) fetch_async_react_component(component_name, , &block) end end |
#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:
-
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.
-
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.
-
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
-
Provide boolean values for ‘:if` or `:unless` to conditionally use caching.
-
Optionally provide the ‘:cache_tags` option: String or Array (or Proc, or any object responding to `cache_key`, such as an ActiveRecord model) of revalidation tags. Tagged cache entries can be deleted later with `ReactOnRailsPro.revalidate_tag(tag)`. Tag revalidation is best-effort, so also set `cache_options: { expires_in: … }` to bound staleness.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 76 def cached_react_component(component_name, = {}, &block) ReactOnRailsPro::Utils.with_trace(component_name) do (, block) fetch_react_component(component_name, ) do = [:props] = yield [:skip_prerender_cache] = true [:auto_load_bundle] = ReactOnRails.configuration.auto_load_bundle || [:auto_load_bundle] react_component(component_name, ) 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:
-
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.
-
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.
-
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
-
Provide boolean values for ‘:if` or `:unless` to conditionally use caching.
-
Optionally provide the ‘:cache_tags` option: String or Array (or Proc, or any object responding to `cache_key`, such as an ActiveRecord model) of revalidation tags. Tagged cache entries can be deleted later with `ReactOnRailsPro.revalidate_tag(tag)`. Tag revalidation is best-effort, so also set `cache_options: { expires_in: … }` to bound staleness.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 107 def cached_react_component_hash(component_name, = {}, &block) [:prerender] = true ReactOnRailsPro::Utils.with_trace(component_name) do (, block) fetch_react_component(component_name, ) do = [:props] = yield [:skip_prerender_cache] = true [:auto_load_bundle] = ReactOnRails.configuration.auto_load_bundle || [:auto_load_bundle] react_component_hash(component_name, ) 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:
-
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.
-
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.
-
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
-
Provide boolean values for ‘:if` or `:unless` to conditionally use caching.
-
Optionally provide the ‘:cache_tags` option: String or Array (or Proc, or any object responding to `cache_key`, such as an ActiveRecord model) of revalidation tags. Tagged cache entries can be deleted later with `ReactOnRailsPro.revalidate_tag(tag)`. Tag revalidation is best-effort, so also set `cache_options: { expires_in: … }` to bound staleness.
273 274 275 276 277 278 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 273 def cached_stream_react_component(component_name, = {}, &block) ReactOnRailsPro::Utils.with_trace(component_name) do (, block) fetch_stream_react_component(component_name, , &block) end end |
#fetch_react_component(component_name, options) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 25 def fetch_react_component(component_name, , &) if ReactOnRailsPro::Cache.use_cache?() cache_key = ReactOnRailsPro::Cache.react_component_cache_key(component_name, ) Rails.logger.debug { "React on Rails Pro cache_key is #{cache_key.inspect}" } = ReactOnRailsPro::Cache.([:cache_options]) if ReactOnRailsPro::Cache.cache_write_expired?([:cache_options]) return render_expired_cache_miss(cache_key, &) end cache_hit = true = [] result = Rails.cache.fetch(cache_key, ) do cache_hit = false = ReactOnRailsPro::Cache.([:cache_tags]) yield end ReactOnRailsPro::Cache.(, cache_key, ) unless cache_hit if cache_hit = ReactOnRails::ReactComponent::RenderOptions.new( react_component_name: component_name, options: ) load_pack_for_generated_component(component_name, ) 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
This helper requires React Server Components support to be enabled in your configuration: ReactOnRailsPro.configure do |config|
config.enable_rsc_support = true
end
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:
244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 244 def rsc_payload_react_component(component_name, = {}) # rsc_payload_react_component doesn't have the prerender option # Because setting prerender to false will not do anything [:prerender] = true # Extract streaming-specific callback on_complete = .delete(:on_complete) consumer_stream_async(on_complete:) do internal_rsc_payload_react_component(component_name, ) end end |
#rsc_payload_react_component_with_async_props(component_name, options = {}, &props_block) ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 184 def rsc_payload_react_component_with_async_props(component_name, = {}, &props_block) unless ReactOnRailsPro.configuration.enable_rsc_support raise ReactOnRailsPro::Error, "rsc_payload_react_component_with_async_props requires enable_rsc_support to be true. " \ "Async props depend on React Server Components. " \ "Set `config.enable_rsc_support = true` in your ReactOnRailsPro configuration." end [:async_props_block] = props_block rsc_payload_react_component(component_name, ) 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.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 155 def stream_react_component(component_name, = {}) # stream_react_component doesn't have the prerender option # Because setting prerender to false is equivalent to calling react_component with prerender: false [:prerender] = true if .key?(:immediate_hydration) ReactOnRails::Helper.warn_removed_immediate_hydration_option("stream_react_component") .delete(:immediate_hydration) end # Extract streaming-specific callback on_complete = .delete(:on_complete) consumer_stream_async(on_complete:) do internal_stream_react_component(component_name, ) end end |
#stream_react_component_with_async_props(component_name, options = {}, &props_block) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 |
# File 'app/helpers/react_on_rails_pro_helper.rb', line 172 def stream_react_component_with_async_props(component_name, = {}, &props_block) unless ReactOnRailsPro.configuration.enable_rsc_support raise ReactOnRailsPro::Error, "stream_react_component_with_async_props requires enable_rsc_support to be true. " \ "Async props depend on React Server Components. " \ "Set `config.enable_rsc_support = true` in your ReactOnRailsPro configuration." end [:async_props_block] = props_block stream_react_component(component_name, ) end |