⚡
React脳からRails Hotwireを触るときは思考転換が必要
- 最近Railsを学び直している。単体でなんとかしたい、という気持ち。One Person Framework.
- Reactから来たひとがHotwireを使うならJSON操作脳から思考の転換をする必要がある
- React(SPA+API)開発とRails(のみ)開発の根本的な発想の違いを抑える。
考え方の違い
- React+APIの考え方
- クライアント側からAPIを叩いてJSONデータを取得する
- 取得したJSONを元にクライアントJSが選択肢やデータを組み立てて表示する
- Rails Hotwireの考え方
- データの操作は基本的にHTTPアクションを通じてのみ行う
- HTMLとHTTPでの操作が正である
- サーバー側が構築したHTMLの断片を受け取りDOMを差し替える
- StimulusはHTMLのちょっとした操作を拡張するためのものとして捉える
具体例の比較
- 要件としてselectで選んだデータに紐づく詳細を下に表示するUIを作る
Reactの発想
- GETリクエストでJSONを取得してJSで組み立てる
const handleChange = async (e) => {
const res = await fetch(`/api/items/${e.target.value}`);
const json = await res.json();
setSelectedItem(json);
};
return (
<select onChange={handleChange}>
<option value="1">Item 1</option>
</select>
<Detail data={selectedItem} />
);
Rails Hotwireの発想
- selectのchangeをStimulusが受け取る
- StimulusがHTTP POSTでsubmitを実行する
- サーバー側がパーシャルからHTMLを生成する
- Hotwire StreamsがHTMLを差し替える
<form data-controller="auto-submit" action="/items/select" method="post">
<select name="item_id" data-action="change->auto-submit#submit">
<option value="1">Item 1</option>
<option value="2">Item 2</option>
</select>
</form>
<div id="detail-area">
最初の状態だよ〜差し替えられるよ〜
</div>
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
submit() {
this.element.requestSubmit()
}
}
class ItemsController < ApplicationController
def select
@item = Item.find(params[:item_id])
respond_to do |format|
format.turbo_stream
end
end
end
<%= turbo_stream.update "detail-area" do %>
<div><%= @item.name %></div>
<div><%= @item.description %></div>
<% end %>
結論
- ReactのGETでJSONを取ってきてJSで組み立てる発想を捨てる
- サーバーにリクエストを送りサーバーが返したHTMLでDOMを置き換える前提を持つ
- StimulusはHTMLの延長で、HTTPリクエストを発生させるトリガーとして使う。単体でAPIを叩いてDOM変えるなどしない。
Discussion