The All-Stimulus App

Let's look at what the React page looks like in Stimulus in this lesson.

We'll cover the following

You may have noticed something about the two main examples in this course: they are slightly tuned to what we thought might be the strengths of each framework. The Stimulus page is, well, Stimulus-y. It has a lot of text markup, and the interaction is mostly deciding whether to show or hide things based on filters. The React page is more… reactive. There’s more text and just a little bit more of a state that depends on another state.

But what happens if you swap?

We thought it’d be interesting to close out the course by showing what the React page looks like in Stimulus and vice versa. We didn’t add any new tools to the app to do this.

To answer your possible first question, we don’t think there was a dramatic difference in how long one version or the other version took. We’ve been working with these samples for a long time, and the underlying logic mostly transferred. If forced to choose, converting the schedule page to React was probably longer; it’s certainly more verbose.

While it’s not exactly an apples-to-apples comparison, the React versions of both pages are about an extra one-third lines of code (roughly 525 to 400).

Some of this is TypeScript boilerplate. React encourages the creation of more domain objects, and, in conjunction with TypeScript, that just means more code devoted to defining types. So, the difference would likely be slightly less pronounced if you just wrote JavaScript.

Some of this is React boilerplate, component definitions, messing around with reducers, and extra server-side code to shape the data a little bit. It’s a general feature of JavaScript style that there is more typed boilerplate than in Rails style. Rails tends to avoid boilerplate code where possible; most JavaScript frameworks tend to have more of it. Also, React encourages smaller components, which means more boilerplate in terms of declarations, headers, and the like.

Subjectively, we were able to get the bones of the system set up faster in Stimulus, but the actual connection of domain logic and view code was faster in React, which makes sense since connecting domain logic and display is basically what React does.

React encourages a separate presentation and domain logic, which means that you can do a lot of work within the domain logic, and the presentation will just automatically change. So, the last step in React is very satisfying. It also means that Stimulus is letting you take a shortcut for simple interactions that don’t require a lot of domain logic. As the Stimulus logic becomes more complex, you end up building in the domain logic and reactivity that React gives you.

Here’s a tour of both apps. We’re not showing the creation of each app in pieces, but we did the pure display first and then added each interactive element. We also used the Cypress tests to ensure we were matching functionality.

The All-Stimulus app

To build the concert display and ticket purchase page in Stimulus, we needed to do the following:

  • Unroll the markup from the React components and go back to an ERB template
  • Add the interaction for changing the number of tickets to buy, which also changes the status of seats from valid to invalid and vice versa
  • Add the interaction for clicking on a seat, which updates the status of that seat, the seats to its left and right (which might be purchased or become invalid), and updates the subtotal
  • Add the interaction for the “Clear All” button
  • Add some CSS for seats and hovers.
  • Add ActionCable functionality for communicating with the server

We had a couple of design decisions to make. We decided to try and put as much state as possible in the markup itself rather than use a reducer or other kind of central state object. Then, we had to decide where to put the Stimulus controllers, the design issue being that clicking on a seat causes a change to the subtotal, which is rather far away on the page. Ultimately, we decided on one Stimulus controller for the whole page, with a lot of the domain logic of managing the status of seats pulled into a plain TypeScript class.

It’s worth noting that there is another option here, which is to move all the seat interaction logic to the server and force a page refresh whenever you interact with the dropdown or click a seat. This is exactly the kind of interaction that Turbolinks exists to manage. We didn’t write it this way because we wanted to show how the client-side logic translates, but, in practice, the server-side solution is also relatively simple and clear.

Here’s the ERB template, pulled from the markup. We did not need to change the server-side code at all—the necessary data was already available:

Get hands-on with 1200+ tech skills courses.