LEFログ:学習記録ノート

leflog: 学習の記録をどんどんアップしていきます

Rails 7 の jsbundling-rails (esbuild) で、viewファイルからReactへとデータを渡す方法と、Mount処理を簡単にする方法(props, erb, slim)

結論

こちらのPull Requestとコミット履歴を参考にしてみてください。

追記(2023-03-24)

更にエンドポイントの処理を便利にしてみました。

解説

Rails 6ではviewファイルからデータを渡すときには、react-railsgemのおかげで、次のように書くことができます。

react_component('Reports', userId: @user.id, practices: @user.practices)

ReactをRailsと共に使う方法 - Qiita

この方法で、erbなどのviewファイルからReactへとデータを渡すことができます。

しかし、Rails 7でjsbundling-rails(esbuild)を選択したとき、この上記のgemを使わずに、同じようなコードを書くにはどうしたら良いでしょうか?

jsbundling-rails関係の情報はネット上にほとんどなく、調べるのにかなり苦労しました。そのため、ブログ記事にまとめようと思いました。

方法

content_tagを使ってあげる必要があります。

<%= content_tag :div, id: "hello", data: {name: "ゾウ", age: 42}.to_json do %><% end %>

このように書いてあげることで、React側へとデータを渡すことができます。

React側は、

import Hello from "./components/Hello"
const hello = document.getElementById('hello');
const helloData = JSON.parse(hello.getAttribute('data'))
createRoot(hello).render(<Hello name={helloData.name} age={helloData.age} />);

エンドポイントにこんな感じで書いてあげれば画面に反映される(Mount処理ができる)のですが、このままだと新しいコンポーネントが増えるたびにエンドポイントのコードが増えて、ごちゃごちゃになってしまいます。

なので、

const Mount = (Component, mountNodeId) => {
  const mountNode = document.getElementById(mountNodeId);
  const props = JSON.parse(mountNode.getAttribute("data"));
  createRoot(mountNode).render(<Component {...props} />);
};

こんな感じでコードを書いてあげて、この関数を何度も再利用すれば、エンドポイントのコードがすっきりします。

.render(<Component {...props} />)のおかげで、コンポーネントに渡す引数が幾つであっても対応できるようになります。

ReactコンポーネントへのPropsの渡し方/受け取り方大全

具体的な書き方が分からない場合は、上記の「結論」にあるPull Requestを読むと、すぐに理解できると思います。

こんな感じでエンドポイントのMount処理がスッキリします