Skip to main content
Version: 17.x (stable)

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-renderer and 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 setStore call 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: false in the renderer configuration, or RENDERER_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, and react-server-dom-webpack together to 19.3.1, or all three to 19.2.9 on the 19.2 line, and commit the refreshed lockfile. The patched react-server-dom-webpack peers on the matching React version. If a copy nested under react-on-rails-rsc stays behind, pin it with npm overrides, pnpm pnpm.overrides, or Yarn resolutions.
  • Check what your lockfile resolves with pnpm why react-server-dom-webpack (pnpm -r why from the root of a pnpm workspace, or the npm or Yarn equivalent), or run bundle exec rake react_on_rails:doctor from 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 fastify 5.12.6 or later, so an existing lockfile cannot keep a fastify affected 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 read railsContext.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 renderingError is present.
  • Rspack server bundles no longer write a stray ssr-generated/manifest.json. Existing Rspack apps can apply the same plugin filter in config/rspack/serverWebpackConfig.js; see the CHANGELOG entry.
  • unstable_cache no longer throws BUILD_ID not set on RSC payload requests that reach a fresh renderer worker.