How can i make document.addEventListener 'turbolinks:load' run when i came from link_to helper via react Webpacker on Rails 5?

3.4k views Asked by At

So my project is using react with Webpacker on Rails 5. If i go to the page by link_to helper seems like javascript under document.addEventListener('turbolinks:load') not working.

This is my root controller insurance_form_container.jsx

import React from 'react'
import ReactDOM from 'react-dom'
import StartForm from './insurance_form/start_form'

console.log('root react')

document.addEventListener('turbolinks:load',function () {
  ReactDOM.render(
    <StartForm />,
    document.getElementById('start-form-index-container')
  )
})

This is my html template for this route

<div class="container">
  <div id="start-form-index-container">

  </div>
</div>

<%= content_for(:footer) do %>
    <%= javascript_pack_tag('insurance_form_container') %>
<% end %>

This is my link form the other page.

<%= link_to users_insurance_form_start_path,
            class: 'btn btn-lg btn-success btn-primary-green' do %>
    ดำเนินการต่อ
<% end %>

Seems like console.log('root react') is running correctly but ReactDOM.render is not running at all. Unless if i refresh the page it is loading correctly.

Am i missing something? How can i make .jsx code running through link_to helper?

Thanks!

2

There are 2 answers

1
Mshka On

I think it is doing what you are telling it to do. It adds an Event Listener (but that happens after the turbolinks:load event). So it only executes after you navigate to another page, which would be the first turbolinks:load event after you add the listener.

If you are putting it on that page, and you want it to execute on page load, don't put it inside of an event listener How about using on event trigger

document.on("turbolinks:load", function() {
  ReactDOM.render(
   <StartForm />,
   document.getElementById('start-form-index-container')
  )
});
0
dtbaker On

Hey this happened to me as well.

For anyone else, I was bundling my react code in the head along with the other stimulus code. That is too early for adding document event listeners.

I split the react code from the main bundle, and loaded it into the footer of the website. Now I can do this:

import * as React from 'react'
import ReactDOM from 'react-dom/client'
import App from "./App"

const initReactPage = () => {
    const element = document.getElementById('js-robot-ui')
    if(element) {
        const root = ReactDOM.createRoot(element)
        const config = JSON.parse(element.dataset.config)
        root.render(<App config={config}/>)
    }
}

document.addEventListener("turbolinks:load", initReactPage)
initReactPage()