diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb7b0c9b..ce4e35c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,9 @@ Changes since the last non-beta release.
_Please add entries here for your pull requests that have not yet been released. Include LINKS for PRs and committers._
+#### Fixed
+- Preserve default controller layouts for `render component:` after the Rails 8 render pipeline change reported in #1356.
+
## [3.3.0] - 2026-03-31
#### Added
diff --git a/lib/react/rails/railtie.rb b/lib/react/rails/railtie.rb
index 90e856a1..6aa11650 100644
--- a/lib/react/rails/railtie.rb
+++ b/lib/react/rails/railtie.rb
@@ -66,7 +66,7 @@ class Railtie < ::Rails::Railtie
ActionController::Renderers.add :component do |component_name, options|
renderer = ::React::Rails::ControllerRenderer.new(controller: self)
html = renderer.call(component_name, options)
- render_options = options.merge(inline: html)
+ render_options = Railtie.component_render_options(options, html)
render(render_options)
end
end
@@ -121,6 +121,13 @@ def self.append_react_build_to_assets_version!(assets, react_build)
versioned_assets.version = [versioned_assets.version, "react-#{react_build}"].compact.join("-")
end
+ def self.component_render_options(options, html)
+ render_options = options.merge(inline: html)
+ return render_options if render_options.key?(:layout)
+
+ render_options.merge(layout: true)
+ end
+
def self.versioned_assets_for(assets)
return assets if versioned_assets?(assets)
diff --git a/test/react/rails/component_renderer_test.rb b/test/react/rails/component_renderer_test.rb
new file mode 100644
index 00000000..19d3b080
--- /dev/null
+++ b/test/react/rails/component_renderer_test.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class ComponentRendererController < ActionController::Base
+ append_view_path File.expand_path("../../dummy/app/views", __dir__)
+ layout "application"
+
+ def default_layout
+ render component: "TodoList"
+ end
+
+ def explicit_layout_false
+ render component: "TodoList", layout: false
+ end
+end
+
+class ComponentRendererTest < ActionController::TestCase
+ tests ComponentRendererController
+
+ FakeRenderer = Struct.new(:html, :calls) do
+ def initialize(html)
+ super(html, [])
+ end
+
+ def call(component_name, options)
+ calls << [component_name, options]
+ html
+ end
+ end
+
+ setup do
+ @routes = ActionDispatch::Routing::RouteSet.new
+ @routes.draw do
+ get "default_layout", to: "component_renderer#default_layout"
+ get "explicit_layout_false", to: "component_renderer#explicit_layout_false"
+ end
+ end
+
+ test "render component uses the current layout by default" do # rubocop:disable Minitest/MultipleAssertions
+ fake_renderer = FakeRenderer.new("