コンセプト
<a>
タグや<form>
タグのメリットReactでインタラクティブな動作をさせる時、<a>
タグを使用せずに<button>
タグにonClick
等のイベントハンドラーをつけることが多いです。同様にformを送信する場合も<form>
タグにaction
属性をつけずに、代わりにonSubmit
のイベントハンドラをつけて処理するのが一般的です。このようにReactはブラウザネイティブの機能を使わずに、カスタムで動作を作ることが多いです。
Hotwireはこの逆です。Hotwireではなるべくブラウザ本来の機能を使います。
ブラウザ本来の機能を使うメリットは以下のものが挙げられます。
<a>
タグや<form>
タグは動作しますので、プログレッシブエンハンスメントになります。つまりJavaScriptが読み込まれていなくてもウェブサイトが動作します<a>
タグのhref
はデフォルトでマウスホバー時にprefetchされます。つまりリンクをクリックする前に、Turboがフライングをしてリンク先のウェブページをロードします。このため、非常にレスポンスが速いUI/UXが得られます<a>
タグにdata-turbo-method
属性を追加すると、GET以外のHTTPメソッドを使えます。HTMLの構造上、<form>
が使いにくい時に便利です。(ただし非GETはなるべく<form>
を使うことが推奨されています)<a>
タグおよび<form>
にdata-turbo-frame
属性を追加すると、サーバから返ってきたレスポンスを任意のTurbo Frameに転送できます<form>
に含まれる<button>
や<input>
にdata-turbo-submits-with
を追加すると、送信中にボタンのテキストを自動的に変更できます。これだけでPending UI(待ちUI)が実現できます<a>
タグや<form>
タグによってリクエストを送信すると、適切なHTML要素にaria-busy
属性が付きます。アクセシビリティ的に有効な上に、これをCSS擬似セレクタで読み取れば待ちUIがCSSだけで作れます<form>
にdata-turbo-confirm
属性をつけると、form送信時に最終確認用のモーダルダイアログを表示できます。これはデフォルトではブラウザネイティブのwindow.confirm()
が使用されますが、カスタマイズして任意のダイアログを表示できます上記のように、Hotwireでは<a>
タグや<form>
タグを使えば数多くの便利機能がついてきます。onClick
を使ってカスタムのイベントハンドラを書くのではなく、なるべくブラウザの標準機能で引っ張り、少しでもライブラリに多くの仕事をさせるのがHotwireを便利に使いこなすコツの一つだと思います。
<a>
タグや<form>
タグを使います
click
イベントではなく、例えばinput
やchange
イベントに応答するときは適宜対応するStimulus Controllerを書きます <button>
タグにonclick
を書いて、そのハンドラからサーバにfetch
するようなコードは滅多に書きません
<button>
タグにStimulusを繋げます Turboを使ってサーバとの非同期通信をスタートさせる場合、<a>
タグや<form>
タグが推奨されているのは上述した通りです。でも<a>
タグや<form>
タグとは無関係に、JavaScriptからリクエストを送信したい場合もあります。そしてTurbo.visit([url])
でそれが可能なことも紹介しました。しかし実は、ここには制限があります。Turbo.visit()
はGETメソッドしか送信できないのです。
POST用のメソッドを用意しないなど、TurboではJavaScriptから送信できるリクエストを敢えて制限しています。JavaScriptから非GETのTurboリクエストを送信しにくくしているのです。なるべく<form>
タグを作って、プログレッシブエンハンスメントできるように書きなさいと言われているかのようです。
どうしてもJavaScriptから自由にTurboを使いたい場合はrequest.jsがあります。これはGitHubのrails
リポジトリにありますので、Railsのチームで管理をしているものです(安心して使えます)。request.jsはCSRFトークンの送信や返ってきたTurbo StreamをDOMに挿入する処理もしてくれますので、Turboと一緒に使うときは便利です。