You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/oss/api-reference/view-helpers-api.md
+12-4Lines changed: 12 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ Uncommonly used options:
24
24
id:nil,
25
25
```
26
26
27
-
-**component_name:** Can be a React component, created using a React Function Component, an ES6 class or a Render-Function that returns a React component (or, only on the server side, an object with shape `{ renderedHtml, clientProps?, redirectLocation?, routeError? }`), or a "renderer function" that manually renders a React component to the DOM (client-side only). Note, a "renderer function" is a special type of "Render-Function." A "renderer function" takes a 3rd param of a DOM ID.
27
+
-**component_name:** Can be a React component, created using a React Function Component, an ES6 class or a Render-Function that returns a React component (or, only on the server side, an object with shape `{ renderedHtml, clientProps?}`), or a "renderer function" that manually renders a React component to the DOM (client-side only). Note, a "renderer function" is a special type of "Render-Function." A "renderer function" takes a 3rd param of a DOM ID. The legacy `redirectLocation` and `routeError` return fields are still supported but deprecated — see the [Render-Functions Guide](../core-concepts/render-functions.md#8-redirect-information-legacy) for modern alternatives.
28
28
All options except `props, id, html_options` will inherit from your `react_on_rails.rb` initializer, as described [here](../configuration/README.md).
29
29
-**general options:**
30
30
-**props:** Ruby Hash which contains the properties to pass to the React object, or a JSON string. If you pass a string, we'll escape it for you.
@@ -51,10 +51,11 @@ Uncommonly used options:
51
51
`react_component_hash` is used to return multiple HTML strings for server rendering, such as for
52
52
adding meta-tags to a page. It is exactly like react_component except for the following:
53
53
54
-
1.`prerender: true` is automatically added to options, as this method doesn't make sense for
55
-
client only rendering.
56
-
2. Your JavaScript Render-Function for server rendering must return an Object rather than a React Component.
54
+
1.**`prerender: true` is always forced** — even if you pass `prerender: false`, it is silently overwritten. This helper only makes sense for server rendering.
55
+
2. Your JavaScript Render-Function for server rendering must return an Object with a `renderedHtml` property containing `componentHtml` and any other keys.
57
56
3. Your view code must expect an object and not a string.
57
+
4. Cannot be used with renderer functions (3-parameter functions) — these are client-only.
58
+
5. The `immediate_hydration` option is no longer supported — if passed, it will be ignored with a deprecation warning.
58
59
59
60
Here is an example of ERB view code:
60
61
@@ -91,6 +92,10 @@ You can call `rails_context` or `rails_context(server_side: true|false)` from yo
91
92
92
93
---
93
94
95
+
For a complete table of which component/return types work with each helper, see the [Compatibility Matrix](../core-concepts/render-functions.md#compatibility-matrix) in the Render-Functions guide.
96
+
97
+
---
98
+
94
99
### Renderer Functions (function that will call ReactDOM.render or ReactDOM.hydrate)
95
100
96
101
A "renderer function" is a Render-Function that accepts three arguments (rather than 2): `(props, railsContext, domNodeId) => { ... }`. Instead of returning a React component, a renderer is responsible for installing a callback that will call `ReactDOM.render` (in React 16+, `ReactDOM.hydrate`) to render a React component into the DOM. The "renderer function" is called at the same time the document ready event would instantiate the React components into the DOM.
@@ -155,6 +160,9 @@ Progressive server-side rendering using React 18+ streaming with `renderToPipeab
155
160
- Progressive page loading with Suspense boundaries
156
161
- Better perceived performance
157
162
163
+
> [!IMPORTANT]
164
+
> `stream_react_component` always forces `prerender: true`, even if you pass a different value. The `immediate_hydration` option is no longer supported and will be ignored with a warning if passed. It only works with React components or render functions that return React components — it does not support render functions returning `{ renderedHtml }` objects.
165
+
158
166
See the [Streaming Server Rendering guide](../building-features/streaming-server-rendering.md) for usage details.
Copy file name to clipboardExpand all lines: docs/oss/building-features/react-router.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -181,6 +181,21 @@ For a practical example of route organization, see the [routes configuration fil
181
181
182
182
**Note:** This tutorial uses a legacy directory structure (`client/app/bundles`) from earlier React on Rails versions. Modern projects use `app/javascript/src/` structure as shown in this guide. The React Router integration patterns remain applicable.
183
183
184
+
## `<Navigate>` Component SSR Behavior
185
+
186
+
When using React Router's `<Navigate>` component with server-side rendering, be aware of the following behavior:
187
+
188
+
-**During SSR, `<Navigate>` is a no-op.** It renders `null` because `useEffect` does not fire on the server. No redirect is performed — Rails still sends the full response with whatever HTML was rendered.
189
+
-**The redirect only fires on the client** via `useEffect`, which runs after hydration. This means:
190
+
- Users briefly see the SSR content before being redirected (content flash).
191
+
- Search engines see the original page content, not a redirect — there is no HTTP 301/302 status code.
192
+
- The client-side redirect adds a navigation entry to the browser history.
193
+
194
+
**Recommendations for SSR redirects:**
195
+
196
+
1.**Prefer Rails controller redirects** for auth guards, canonical URLs, and SEO-critical redirects. Check conditions in your controller and call `redirect_to` before rendering.
197
+
2.**Use `<Navigate>` only for client-side routing transitions** where a brief flash is acceptable and SEO redirect semantics are not needed.
198
+
184
199
## Additional Resources
185
200
186
201
-[React Router Official Documentation](https://reactrouter.com/)
> React on Rails does not perform actual page redirections. Instead, it returns an empty component and relies on the front end to handle the redirection when the router is rendered. The `redirectLocation` property is logged in the console and ignored by the server renderer. If the `routeError` property is not null or undefined, it is logged and will cause Ruby to throw a `ReactOnRails::PrerenderError` if the `raise_on_prerender_error` configuration is enabled.
127
+
> **`redirectLocation` and `routeError` have significant limitations.** These fields originated from React Router v3/v4 integrations but are still supported at the runtime level. Be aware of:
128
+
>
129
+
> -`redirectLocation` does **not** trigger an actual server-side redirect — Rails still returns the same response with an empty `<div>`. The redirect only takes effect once the client-side router renders.
130
+
> -`routeError` only triggers `raise_on_prerender_error` behavior (if enabled) — it does not produce a user-facing error page.
131
+
> - Modern React Router v6 Declarative Mode (`StaticRouter`) has no mechanism to produce these values.
132
+
> - React Router v6 Data Mode (`createStaticHandler`) handles redirects via `Response` objects, not these fields.
133
+
>
134
+
> **Modern alternatives:**
135
+
>
136
+
> - For redirects during SSR, handle them in your Rails controller (e.g., check auth before rendering).
137
+
> - For client-side redirects, use `<Navigate to="/path" />` (note: this is a [no-op during SSR](../building-features/react-router.md#navigate-component-ssr-behavior)).
138
+
> - For route errors, use React Router's `errorElement` or an `ErrorBoundary`.
128
139
129
140
```jsx
141
+
// Legacy pattern — prefer modern alternatives above
@@ -143,12 +155,17 @@ Take a look at [serverRenderReactComponent.test.ts](https://github.com/shakacode
143
155
144
156
2.**Objects Require Specific Properties** - Non-promise objects must include a `renderedHtml` property to be valid when used with `react_component`.
145
157
146
-
3.**Async Functions Support Server Render Hashes** - When using the React on Rails Pro Node renderer, async render-functions can return React components, strings, or full server render hashes, including `clientProps`, `redirectLocation`, and `routeError`. See [8. Redirect Information](#8-redirect-information).
158
+
3.**Async Functions Require the Pro Node Renderer** - Async render-functions (returning Promises) only work with the React on Rails Pro Node renderer. With ExecJS, an async render function silently returns `'{}'` with only a `console.error` — the empty result can be confusing to debug.
147
159
148
160
4.**`clientProps` are merged back into hydration props** - If a server render result includes `clientProps`, React on Rails merges those keys into the client hydration props generated by `react_component`.
149
161
- Use this to pass server-only computed hydration data (for example router dehydrated state).
150
162
- Merge order is `original_props.merge(clientProps)`, so keys from `clientProps` override matching original keys.
151
163
- This merge requires your original `props:` to be a Ruby `Hash` or a JSON string representing an object.
164
+
- The merge handles symbol vs. string key coexistence: if `clientProps` contains a string key `"foo"` and the original props contain a symbol key `:foo`, the merge updates the existing symbol key rather than creating a duplicate. An error is raised if both string and symbol versions of the same key exist in the original props.
165
+
166
+
5.**Server render result detection is broad** - React on Rails treats any object containing a `renderedHtml`, `redirectLocation`, `routeError`, or `error` key as a server render result (not a React component). This means returning an object with an `error` key from a render function triggers server-render-hash processing rather than being treated as a React component. Note that `error` is only used for detection — it is not itself treated as an exception descriptor. Only `routeError` sets the error flag during processing. This may be surprising if you intended `error` as a regular data field.
167
+
168
+
6.**Don't return JSX directly from render functions** - Render functions should return a React component (function or class), not a React element (JSX). Returning JSX directly causes React Hooks to break silently. A deprecation warning is logged but the code currently still works for backward compatibility.
152
169
153
170
## Ruby Helper Functions
154
171
@@ -179,6 +196,9 @@ If your render-function returns `clientProps`, this helper also injects those va
179
196
180
197
The `react_component_hash` helper is used when your render function returns an object with multiple HTML strings. It allows you to place different parts of the rendered output in different parts of your layout.
181
198
199
+
> [!IMPORTANT]
200
+
>`react_component_hash`**always forces `prerender: true`**, even if you explicitly pass `prerender: false`. This is because the helper only makes sense for server rendering — it needs the server to produce the hash of HTML strings. Passing`prerender: false` will be silently overwritten.
201
+
182
202
```ruby
183
203
# With a render function that returns an object with multiple HTML properties
>**Note:** ❌ marks an unsupported combination. Some mismatches raise a `ReactOnRails::Error` directly inRuby (e.g., `react_component` with a hash result raises `"Use react_component_hash (not react_component)..."`, and`react_component_hash` with a non-hash result raises `"Render-Function... expected to return an Object"`). Others (renderer functions used in server rendering, ProNode renderer mismatches) throw a JavaScript error that becomes `ReactOnRails::PrerenderError`when`raise_on_prerender_error` is enabled, or is embedded as an error comment in the HTMLwhen it is not. Either way, these combinations are not silent data failures — they will surface as errors or visible error output.
256
+
257
+
**Keyconstraints:**
258
+
259
+
-**`react_component_hash`** always forces `prerender: true` — it cannot be used for client-only rendering.
260
+
-**`stream_react_component`** (Pro) always forces `prerender: true`. The`immediate_hydration` option is no longer supported and will be ignored with a warning if passed.
261
+
-**Renderer functions** (3 parameters) are client-only — they call `ReactDOM.render`/`hydrate` directly, so server rendering with them throws an error.
262
+
-**Async render functions** (returning Promises) require the ProNode renderer. WithExecJS, they silently return`'{}'`.
>This is a legacy pattern from ReactRouter v3/v4. See [8. RedirectInformation (Legacy)](#8-redirect-information-legacy) for modern alternatives. The `redirectLocation` does not trigger an actual server-side redirect — Rails returns an empty `<div>` and the redirect only fires on the client.
362
410
363
411
```jsx
412
+
// Legacy pattern — prefer handling redirects in your Rails controller
Copy file name to clipboardExpand all lines: docs/oss/getting-started/using-react-on-rails.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -192,13 +192,13 @@ For advanced server rendering (like routing + hydration state), you can return a
192
192
({
193
193
renderedHtml: {
194
194
componentHtml,
195
-
redirectLocation,
196
-
error,
195
+
title,
196
+
metaTags,
197
197
},
198
198
});
199
199
```
200
200
201
-
Use with `react_component_hash` helper for multiple HTML strings (useful with React Helmet for meta tags).
201
+
Use with `react_component_hash` helper for multiple HTML strings (useful with React Helmet for meta tags). Note that `react_component_hash` always forces `prerender: true`.
202
202
203
203
If you also need to send extra data back to the browser for hydration, add `clientProps`:
204
204
@@ -209,13 +209,14 @@ If you also need to send extra data back to the browser for hydration, add `clie
209
209
// Optional: merged into client hydration props on the Rails side
Think of it like this: `renderedHtml` is what the user sees now, and `clientProps` is a lunchbox of data React uses after the page loads.
218
216
217
+
> [!NOTE]
218
+
> The legacy `redirectLocation` and `routeError` return fields (from React Router v3/v4 era) are still supported but deprecated. They do not trigger actual server-side redirects or error pages. See the [Render-Functions Guide](../core-concepts/render-functions.md#8-redirect-information-legacy) for modern alternatives.
219
+
219
220
For complete Render-Function details and examples, see the [Render-Functions Guide](../core-concepts/render-functions.md).
0 commit comments