Hotwire can feel very different when coming from another front end technology such as React. Here are 4 tips to keep in mind when getting started with Hotwire and Rails.
Consider the following example where we want to add inline editing of abilities to a stat sheet for a dungeons and dragons character. The actual diff is quite small (yay Hotwire!) but we can see all 4 tips at play here.
The character show page renders out all of the abilities:
The abilities partial displays the ability along with a link to the edit page. We wrap this in a turbo_frame tag.
The edit page displays a form with a number field to edit the value of a given ability. This diff adds a turbo_frame tag around the form to allow it to be pulled in and replace the show content and enable inline edit.
Instead of taking a Hotwire-first approach, it's usually best to start by creating regular Rails resources and then layering on Hotwire. This allows us to rely on Rails defaults. It is also a form of progressive enhancement, allowing your interaction to work fine with Cmd+click or when users have JS disabled.
Basically, start by pretending Hotwire doesn't exist.
With this approach, you start by building normal Rails pages that link and redirect to each other. Then you can use the various tools that Hotwire provides such as turbo-frames to start composing these pieces together to get an experience that feel a lot more interactive. Even an interaction like inline edit is really just composing regular edit and show pages into some other context. You can see that the diff above is just +4 lines!
Hotwire works best when composing RESTful resources. Working with standard index/show/new/edit actions means that the various URL helpers, form helpers, and , will work nicely for you. It helps you slice up you code into more easily reusable chunks.
Note that these RESTful resources don't need to line up 1:1 with your database. If there's a thing on your page that you want to interact with via Hotwire (e.g. an inline edit), then it deserves to be its own resource. In the code example above, the class is an in-memory object, reified from a column on the characters table. Having a dedicated resource at the routing and controller layers gives us URLs we can hit to perform CRUD actions on abilities via Hotwire.
Thoughtful decomposition of your UI into partials is crucial when developing with Hotwire because you're assembling small pieces of HTML in different contexts. By building things RESTfully, you always have a resource that has an associated partial and responds to and can more easily design form partials tailored to that particular resource.
See the classic talk In Relentless Pursuit of Rest to explore this idea further.
Leaning on dom_id helps keep your ids in sync and avoids a whole class of bugs where you refer to ids in a bunch of places but one place uses underscores and the other uses dashes. In general, you'll want to use it any time you're rendering collections of objects. Use this both to name turbo frames, and arbitrary DOM nodes you want to modify via turbo-stream.
If you're using a custom object that's not ActiveRecord, you can define the to_key method to make it compatible with this helper.
Turbo-frames can be be arbitrarily nested and they can be targeted by other frames, links, and forms. It can be hard to get a sense of what frames you have and how they interact with each other when just reading HTML. Switching to a visual medium can help get a better understanding and debug when you're stuck. This is a variation on the idea that you should stop coding and start drawing.
The simplest way to do this is to take a screenshot of your app and draw some boxes on it. If you want to get fancier, there are some tools such as this browser extension that can automatically detect and higlight frames for you.
These 4 tips were originally shared as part of my RailsConf talk Dungeons & Dragons & Rails where I demonstrated building an interactive D&D character sheet using Rails and Hotwire.