Write Code or Die

RubyやRailsまたはバスケットボールや筋トレについて書きます。

Railsでの部分的なjavascript_pack_tagとturbolinksの共存

最近作りたいアプリケーションがあり、チャット系のUIにしたく勉強がてらRails 5.1 + webpacker + Reactでやってみることにした

しかし、form_with経由のページ遷移した時にページにベタ書きしているjavascript_pack_tagが動かないという事案発生

こんなviewから

#app/view/root/index.html.slim
  .form
    = form_with url: that_path do |form|
      = form.hidden_field :id, value: @id
      = form.submit "submit"

こんなcontrollerを通りthat_pathに遷移する

#app/controller/that_controller.rb

  def create
    that = That.create!(user_id: current_user.id, that_id: params[:that_id])
    redirect_to that_path(id: that.id)
  end

thatはviewの中にjavascript_pack_tagがベタ書きされており

#app/view/that/show.html.slim

#that-container
=javascript_pack_tag('that_container')

このpackではDOMContentLoadedでReactがrenderされるようになっていた

//app/javascript/packs/that_container.js

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <ThatContainer />,
    document.getElementById('workout-container')
  )
})

ここで問題発生。form_withのボタンを押して遷移した時にReact DOMがrenderされない

調べた結果、turbolinksがうまく行ってない感じがした

試しにapp/view/layouts/application.html.erbjavascript_include_tagコメントアウトしてみる

//app/views/layouts/application.html.erb

<head>
  ~

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%#= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

動いた

しかしcssフレームワーク使いたいのでjavascript_include_tagとは共存させたい

でも部分的にReact使いたいだけなので、出来ればturbolinksと共存させたい

こうして泥沼にハマりながら調べた結果

  • javascript_pack_tag<head>に記述する
  • javascript_pack_tagcontent_forで渡しつつ、'data-turbolinks-track':'reload'を指定する

ことで無事解決した

以下コード

//app/views/layouts/application.html.erb

<head>
  ~

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= yield(:javascript_pack_tag) %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
//app/view/that/show.html.slim

= content_for(:javascript_pack_tag, javascript_pack_tag('that_container', 'data-turbolinks-track':'reload'))
#that-container

turbolinksのこともさらっとだが学ぶいい機会になった