Be careful with turbo and view components

… and check why 5600+ Rails engineers read also this

Be careful with turbo and view components

In our project we are using view components to unify button styles in view templates. Something similar to:

class Forms::Button < ViewComponent::Base
  def initialize(type:, text:, options: {}, data: {}, disabled: false)
    @type = type
    @text = text
    @options = options
    @data = data
    @disabled = disabled
  end

  def call
    case @type
    #...
    when "link"
      link_to(
        @options[:href],
        data: @data,
        class: "#{@options[:text_color]} #{@options[:bg_color]} #{css_styles} app-btn",
      ) do
        tag.p(@text)
      end
    end
  end

In order to make a POST request with the given component I’ve decided to make use of the link_to option: method:

  #...
  link_to(
    @options[:href],
    method: @options[:method] || "GET",
    data: @data,
    class: "#{@options[:text_color]} #{@options[:bg_color]} #{css_styles} app-btn",
  )
  #...

And it works. However it turned out there is an issue. Our other component links stopped to work. The link_to with option method will dynamically create an HTML form and immediately submit it. It uses @rails/ujs and it turns out that GET forms are not compatible with turbo stream responses. The fix was to remove the :method option, and use a button_tag for the :post request. Beside of this, since Rails 7 @rails/ujs library is no longer on by default. Also the link_to attriubute “method” is a deprecated. So, do not use it.

You might also like