frequently: → "Should I use Hotwire or StimulusReflex?" → "Will Hotwire kill StimulusReflex?" → "Is Hotwire the StimulusReflex successor?" → "Turbo to replace StimulusReflex?" 5
frequently: → "Should I use Hotwire or StimulusReflex?" → "Will Hotwire kill StimulusReflex?" → "Is Hotwire the StimulusReflex successor?" → "Turbo to replace StimulusReflex?" 6
as fragments of HTML wrapped in self-executing <turbo-stream> elements. → target ID + action, usually via WebSockets → targets can also be CSS selectors (.messages etc.) <turbo-stream action="replace" target="track"> <template> <div id="track"> <audio src="/tracks/1.mp3"> </div> </template> </turbo-stream> 16
Rails, somewhat inspired by Phoenix LiveView → based on CableReady (the "missing ActionCable standard library"1) → initially by Nathan Hopkins (@hopsoft), now maintained by a 4- headed core team → Demo 1 Yours Truly 19
to follow the Rails Golden Path as far as possible 3. In my own apps, I use < 10% Reflexes What follows is an assortment of juxtapositions, distilled into my (very subjective) Best Practices/Heuristics 20
Session Management class TracksController < ApplicationController def show @track = Track.find(params[:id]) session["list_#{@track.list.id}"][:active] = @track end end 30
Session Management class TracksController < ApplicationController def show @track = Track.find(params[:id]) session["list_#{@track.list.id}"][:active] = @track end end ❌ This is a REST violation, we're mutating state on GET instead of POST. 31
Hidden Form & Turbo Streams class ListsController < ApplicationController # PATCH def active_track session["list_#{@list.id}"][:active] = Track.find(list_params[:active_track_id]).list_entry.to_gid.to_s render turbo_stream: turbo_stream.replace(@list) end private def list_params params.require(:list).permit(:active_track_id) end end Problem: There's still (a lot of) flicker ⚡ 33
Update Just a Data Attribute of a Stimulus Controller <turbo-frame id="list"> <div data-controller="list" data-list-active-value="<%= active.id ">...</div> </turbo-frame> <turbo-frame id="active_track"> <div data-controller="player" data-player-active-value="<%= active.id ">...</div> </turbo-frame> ❌ Currently not doable with streams ! Possible remedy: Stream a fragment containing a separate stimulus controller updating just the data attributes 34