Live previews with Rails and StimulusReflex

leastbad

leastbad

Posted on March 24, 2021

Live previews with Rails and StimulusReflex

This morning I read Live previews with Rails and Stimulus 2, a post which compares the experience of implementing a text preview feature using server-rendered code. The author choose to use a "pure Ajax" approach with Stimulus, as well as what the same project would look like using Turbo Frames.

This post will present a 3rd option: StimulusReflex. The full source for this example is available on Github. Don't forget to change to the previews branch!


First, we'll need a template. I'm just going to use a vanilla tag helper:

<%= text_area_tag :body,
                  nil,
                  data: { reflex: "input->Composer#preview" } %>

<div id="preview"></div>
Enter fullscreen mode Exit fullscreen mode

The only thing required to make this feature work is a Reflex declared on the textarea element. input events captured will initiate a preview action on the Composer Reflex class. I also assigned an id attribute to the strong element so that we have a destination for the preview content.

class ComposerReflex < ApplicationReflex
  def preview
    morph "#preview", element.value
  end
end
Enter fullscreen mode Exit fullscreen mode

The preview action takes the value of the element which triggered the Reflex, and updates the #preview element in the browser. Behind the scenes, this is done using one of CableReady's 33 operations, inner_html.

That's it... there are no further steps. You don't need any extra templates, routes or Stimulus controllers.

If you open the Console Inspector, you'll see that each Reflex takes about 5ms, round-trip.


StimulusReflex and CableReady offer a simple but powerful RPC model for building reactive applications. The functionality of this stack eclipses Turbo in every meaningful dimension:

  • CR has ~7x as many verbs/operations as Turbo Streams (just CRUD)
  • CR supports adding custom operations
  • CR is incredibly flexible in terms of who or what you send updates to
  • CR operations can be chained and target multiple elements
  • CR can broadcast from anywhere in your app: jobs, reflexes, controllers, rake tasks, channels
  • CR can provide visual feedback when elements are updated
  • SR provides a transaction wrapper around each request
  • SR has a full life-cycle of events and callbacks on the server and client
  • SR Reflex updates use DOM diffing, not innerHTML, so Stimulus controller state is preserved
  • SR Reflexes can be initiated by JS or declared in markup
  • SR offers a highly performant RPC mechanism with Nothing Morphs
  • SR benefits from tight coupling with Stimulus
  • SR has really powerful server and client debug tooling
  • SR has exceptionally thorough documentation
  • SR has incredible free support
  • SR has a 2000+ person Discord community that is incredibly supportive

I hope that you'll consider updating your post with a third option, Josef!

💖 💪 🙅 🚩
leastbad
leastbad

Posted on March 24, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related