AbstractBrain Answers About us →

Using Rails helpers (x_component) for rendering ViewComponents

Question

ViewComponents are great, but rendering them is not pleasant.

Compared to Rails helpers, I find the syntax of ViewComponents quite verbose…

<%= render(HeadingComponent.new(level: 1)) do %>
  My title
<% end %>

Is there any better solution that is easier to read/write?

For example:

Answer

You can definitely use Rails helpers for syntactic sugar.

In particular, we have found a solution that we really like.

First you need to add this file to your Rails application:

module ComponentsHelper
  COMPONENTS = Dir.glob(Rails.root.join('app', 'components', '*_component.rb'))
  
  COMPONENTS.each do |filename|
    name = File.basename filename, '_component.rb'
    helper = "x_#{name}"
    component = "#{name}_component".camelize.constantize
    define_method(helper) do |*args, **kwargs, &block|
      render(component.new(*args, **kwargs), &block)
    end
  end
end

Then you can use all your components with this simple, short syntax:

<%= x_heading level: 1 do %>
  My title
<% end %>

This is especially nice - and easy to read - when you have many components or nested components. This original code for example:

<%= render(HeadingComponent.new(level: 1)) do %>
  <%= render(IconComponent.new('user')) %>
  <%= current_user.name %>
  <%= render(SecondaryTextComponent.new(color: 'gray')) do %>
    <%= current_user.email %>
  <% end %>
<% end %>

Becomes this:

<%= x_heading level: 1 do %>
  <%= x_icon 'user' %>
  <%= current_user.name %>
  <%= x_secondary_text color: 'gray' do %>
    <%= current_user.email %>
  <% end %>
<% end %>

If you read a page filled with view components, you will notice a great difference in readability.

The x prefix should be read like “custom element”. For example a nav helper may render a nav tag, while x_nav renders your own nav with your application style (e.g. with Tailwind classes). Similar conventions are already used by other frameworks, like Blade.

The prefix also prevents possible collisions between the component helpers generated automatically and normal helpers.

Also x_nav is actually easy to search across all your files, compared to the nav keyword.

Also note that these helpers don’t remove any features from the original gem: you can still use all the components features, including slots.

It’s syntactic sugar and I think that it’s worth it.

This original solution is the one that we have built for AbstractBrain and Pushpad after a lot of research. It’s the closest solution that we found to React-style components using ERB and Rails.

Inspiring articles about this topic include: