Hi guys,
i'm wondering if there is any possibility to use react on rails with async loading like:
<%= javascript_include_tag 'application', async: Rails.env.production? %>
In this case, the componentDidMount does not get fired. The issue is well known, described and fixed here: https://github.com/reactjs/react-rails/issues/218
What i'm searching for is a hook, like ReactRailsUJS.mountComponents(). Right now i'm trying to write something like mountComponents() but i did not have success until now. That's why i'm wondering if i'm missing something?
Thanks a lot in advance.
@SqueezedLight Any research you can do this topic would be greatly appreciated!
I think this already does what you need:
https://github.com/shakacode/react_on_rails/blob/master/node_package%2Fsrc%2FclientStartup.js#L93
function reactOnRailsPageLoaded() {
debugTurbolinks('reactOnRailsPageLoaded');
forEachStore(initializeStore);
forEachComponent(render);
}
We simply need to export the function and expose it here in the main ReactOnRails js class.
https://github.com/shakacode/react_on_rails/blob/master/node_package%2Fsrc%2FReactOnRails.js#L59
Can you try that out and send a PR including:
spec/dummy app to demonstrate this.Thanks!
@justin808 Thanks, i didn't see that in the first place. I'm on it...
@SqueezedLight Any update? Should we leave this issue open?
@justin808 Sorry, i had to manage some really stressful days...
Yes, there is some progress: Exposing reactOnRailsPageLoaded() to ReactOnRails worked like a charm. But i'm using turbolinks 5.0 and i'm calling some code within document.addEventListener("turbolinks:load", function() {}); This peace of code stopped working, because it seems turbolinks does not fire turbolinks:load on initial page load with async script loading. One solution is to use defer instead of async. More information can be found on the issue i opened about this topic: https://github.com/turbolinks/turbolinks/issues/28
So i managed to get everything working with async script loading. I hope i can make the PR on the weekend.
Merged with version 6.0.0-rc.1
If I want to load the js async, do I just add
<%= javascript_include_tag 'application', async: true %>
?
Or is there more settings I need to configure?
@xiaopow I don't know off the top of my head. Please research this and report back to us, and that will help the community.
@xiaopow, @nateberkopec has some done some amazing research into this area. Nate, can you give us a few links to your materials?
I ran into the same problem, where my javascript wasn't executed reliably when loading my generated application.js asynchronously via javascript_pack_tag "application", async: true.
A quick workaround was this snippet:
if (typeof document !== "undefined") {
if (document.readyState !== "loading") {
ReactOnRails.reactOnRailsPageLoaded();
} else {
document.addEventListener("DOMContentLoaded", () =>
ReactOnRails.reactOnRailsPageLoaded(),
);
}
}
I am not sure if I need the event listener since this might be what react_on_rails is doing to initialize the components and it will fail if the DOM had finished loading when the JS is loaded.
Maybe someone knows a better way, or did I miss something from the docs? Nowadays it should be the preferred way to load the JS async (especially when prerendering components).
Is there an official way of doing this in React on Rails now, instead of the solution @dpuscher mentioned above?
@julianguyen I'm sure this is somewhere in the docs.
Here's an example:
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/app/views/layouts/application.html.erb#L17
you need to use defer:
<!-- NOTE: Must use defer and not async to keep async scripts loading in correct order -->
<%= javascript_pack_tag('vendor-bundle', 'data-turbolinks-track': true, defer: true) %>
<%= javascript_pack_tag('app-bundle', 'data-turbolinks-track': true, defer: true) %>
@justin808 Why does 'data-turbolinks-track': true need to be set with defer?
@julianguyen If you don't use turbolinks, you get problems. #1150
@julianguyen if you are not using turbolinks, remove that part.
Most helpful comment
I ran into the same problem, where my javascript wasn't executed reliably when loading my generated
application.jsasynchronously viajavascript_pack_tag "application", async: true.A quick workaround was this snippet:
I am not sure if I need the event listener since this might be what react_on_rails is doing to initialize the components and it will fail if the DOM had finished loading when the JS is loaded.
Maybe someone knows a better way, or did I miss something from the docs? Nowadays it should be the preferred way to load the JS async (especially when prerendering components).