コアコンセプト
StimulusReflexは、WebSockets(ActionCable)とCableReadyを利用してRailsアプリケーション上でリアクティブなリアルタイムUIを実現します。
基本的なReflex
<!-- view.html.erb -->
<button data-reflex="click->Counter#increment">Increment</button>
# app/reflexes/counter_reflex.rb
class CounterReflex < ApplicationReflex
def increment
@count = element.dataset[:count].to_i + 1
end
end
Morphモード
Page Morph(デフォルト)
コントローラアクションを介してページ全体を再レンダリングし、差分のみをDOMに適用します。
Selector Morph
# app/reflexes/example_reflex.rb
class ExampleReflex < ApplicationReflex
def update_metric
morph "#metric-display", render(partial: "metrics/metric", locals: { value: 42 })
end
end
Nothing Morph
クライアントのDOMを更新せずにサーバーサイドのロジックのみを実行します。
class ExampleReflex < ApplicationReflex
def background_task
LongRunningJob.perform_later
morph :nothing
end
end
ライフサイクルメソッド
サーバーサイドコールバック
class ExampleReflex < ApplicationReflex
before_reflex :authenticate
around_reflex :measure_time
after_reflex :log_activity
end
クライアントサイド共通コールバック
beforeReflex(element, reflex, noop, reflexId): WebSocketリクエスト送信前reflexSuccess(element, reflex, noop, reflexId): Reflex実行およびDOM更新完了後reflexError(element, reflex, error, reflexId): サーバーが未補足のエラーを発生させた場合reflexHalted(element, reflex, noop, reflexId): Reflexがthrow :abortで中断された場合afterReflex(element, reflex, noop, reflexId): 成功・失敗にかかわらず常に実行finalizeReflex(element, reflex, noop, reflexId): 最終クリーンアップフック
DOMイベント
stimulus-reflex:beforestimulus-reflex:successstimulus-reflex:errorstimulus-reflex:haltedstimulus-reflex:afterstimulus-reflex:connectedstimulus-reflex:disconnectedstimulus-reflex:ready
実践パターン
フォーム処理
フォーム要素内外で発火したReflexは、自動的にフォーム入力をシリアライズして params へ渡します。
Promiseチェーン
this.stimulate('Comments#create')
.then(() => this.showSuccess())
.catch((err) => this.handleError(err))
永続要素 (Permanent Elements)
data-reflex-permanent を指定した要素は、ページ全体のMorph処理時にも再描画されず保護されます。
<div data-reflex-permanent>
<video id="player" src="video.mp4" controls></video>
</div>