Live previews with Rails and StimulusReflex
Tags: rails, javascript, stimulus, stimulusreflex
Published: 2021-03-24 06:40:36

---
title: Live previews with Rails and StimulusReflex
published: true
description: Contrasting Ajax, Turbo and StimulusReflex approaches
tags: rails, javascript, stimulus, stimulusreflex
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nd4i7zuocfsxmm7e4eod.jpg
---

This morning I read [Live previews with Rails and Stimulus 2](https://nts.strzibny.name/rails-stimulus-live-preview/), 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](https://stimulus.hotwire.dev/), as well as what the same project would look like using [Turbo Frames](https://turbo.hotwire.dev/).

This post will present a 3rd option: [StimulusReflex](https://docs.stimulusreflex.com). The [full source](https://github.com/leastbad/stimulus_reflex_harness/tree/previews) 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:

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

<div id="preview"></div>
```

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.

```rb
class ComposerReflex < ApplicationReflex
  def preview
    morph "#preview", element.value
  end
end
```

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](https://cableready.stimulusreflex.com/reference/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](https://discord.gg/stimulus-reflex) that is incredibly supportive

---

I hope that you'll consider updating your post with a third option, [Josef](https://twitter.com/strzibnyj)!