React on Rails 17.2.1 Release Notes
17.2.1 is a patch release for 17.2.0. Its main fix keeps each request's hydrated Redux stores separate when the Pro Node Renderer serves concurrent server renders. It also carries security updates for React Server Components (RSC) apps and the Node Renderer.
For the complete list of changes, see the CHANGELOG.
Upgrading from 17.2.0 to 17.2.1
Update your gem and npm package versions:
# Gemfile
gem "react_on_rails", "17.2.1"
// package.json
{
"dependencies": {
"react-on-rails": "17.2.1"
}
}
Pro users: Use react-on-rails-pro instead of react-on-rails in package.json, and react_on_rails_pro instead
of react_on_rails in your Gemfile. See the Pro upgrade guide for details.
Then run bundle install and your package manager's install command.
Action required for Pro applications
Upgrade the Node Renderer and JavaScript packages together
On the Pro Node Renderer, ReactOnRails.getStore() called after an await, in streamed content, or in an RSC
Client Component provider could return another concurrent request's store. One user's page could then render with
another user's state. Each render request now gets its own hydrated store registry. See
Issue 5124 and
PR 5133.
- Upgrade
react-on-rails-pro-node-rendererand your React on Rails JavaScript packages in the same deploy. The per-render registry needs both sides. If the renderer deploys separately from your app, isolation starts only once both are upgraded: until then, a request that reaches an old renderer, or an old server bundle on a new renderer, can still share stores as before. Route upgraded bundles only to upgraded renderers during the rollout, and keep concurrent renders that read user-specific stores off the old side until both are upgraded. - Move any
setStorecall at module scope of your server bundle into per-render hydration. Register store generators at module scope, but hydrate user-specific stores from render props. See the Redux store API. - Async work started inside a render, such as a promise chain or a timer when
RENDERER_STUB_TIMERS=false, keeps that render's stores after the render finishes. - Browser store APIs and page lifecycle behavior are unchanged.
- If request scoping causes a problem, set
isolateHydratedStores: falsein the renderer configuration, orRENDERER_ISOLATE_HYDRATED_STORES=false, to restore the shared registry temporarily, and report the problem. See Node Renderer JavaScript configuration.
Refresh react-server-dom-webpack in RSC apps
React published GHSA-xqc2-xf4c-x3h3
(critical, remote code execution) and
GHSA-h3gv-c5rc-p453 (high, denial of
service) on 2026-10-14 against react-server-dom-webpack. Each React line is affected below its patched release:
19.0.9, 19.1.10, 19.2.9, and 19.3.1. React on Rails does not pin that package. Fresh installs already resolve a fixed version, but an existing lockfile keeps the old one.
- Update
react,react-dom, andreact-server-dom-webpacktogether to 19.3.1, or all three to 19.2.9 on the 19.2 line, and commit the refreshed lockfile. The patchedreact-server-dom-webpackpeers on the matching React version. If a copy nested underreact-on-rails-rscstays behind, pin it with npmoverrides, pnpmpnpm.overrides, or Yarnresolutions. - Check what your lockfile resolves with
pnpm why react-server-dom-webpack(pnpm -r whyfrom the root of a pnpm workspace, or the npm or Yarn equivalent), or runbundle exec rake react_on_rails:doctorfrom React on Rails 17.2.1 or later, which warns about affected copies. Doctor runs this check only when RSC support is enabled in the Rails environment it runs in, so confirm it reports RSC as enabled. It also warns when it cannot judge a pnpm copy installed from a tarball, a git repository, or a local file. - Apps that stay on React on Rails 17.2.0 can apply the same dependency update; it needs no gem change. Their Doctor does not have this check, so inspect every resolved copy with the package-manager command above.
Other fixes
- Node Renderer requires
fastify5.12.6 or later, so an existing lockfile cannot keep afastifyaffected by the 5.12.x security releases. Node 18.19 apps that use the documented Fastify 4 override keep it, but no Fastify 4 release fixes the authentication and request-validation bypasses, so move to Node 20 or later. - Fragment-cached components refresh CSP nonces on cache hits, so CSP no longer blocks hydration, console
replay, or streaming scripts from a
cached_*helper. Only nonces the framework emitted are refreshed, so app code that needs a nonce inside a cached component should readrailsContext.cspNonce. Cache keys gain a new segment, so nonce-rendered entries written before upgrading are not reused. Overrides of the private Pro cache helpers must accept their new parameters; the CHANGELOG entry lists them. See CSP caching caveats. - The RSC generator installs React from
~19.3.1, so new RSC apps cannot resolve React 19.3.0. - Inline RSC payloads suppress console replay outside development and test whenever
renderingErroris present. - Rspack server bundles no longer write a stray
ssr-generated/manifest.json. Existing Rspack apps can apply the same plugin filter inconfig/rspack/serverWebpackConfig.js; see the CHANGELOG entry. unstable_cacheno longer throwsBUILD_ID not seton RSC payload requests that reach a fresh renderer worker.