technion
technion

Reputation: 49

Unobtrusive JS with react-rails

I'm currently using Rails with a ReactJS front end. I have most of my JS in an appropriate .js.jsx file, however, I have this sitting in index.html.erb under a script tag:

React.render(
    React.createElement(CommentBox, {url: "/demo"}),
            document.getElementById('content')
        );
</script>

Under this configuration it works perfectly.

I appreciate the usual "Rails Way" is unobstrusive JS, but I'm having a hard time making that happen. If I simply move the above code into my main .js file, it loads before the content element exists and just renders nothing.

React-rails actually provides a special gem for unobtrusive JS, however I have two issues with that. Firstly, the documents don't refer to how to actually attach a URL tag, so neither of these work (no errors, just nothing renders):

<% react_component('CommentBox', url: '/demo') %>
<div data-react-class="CommentBox" data-react-props="url: /demo" />

The bigger issue however, is that the way the react-ujs gem works is by automatically embedding a few hundred lines of JavaScript before the body close tag. This doesn't feel less obtrusive than the four embedded lines I started with, or any improvement over it.

Am I missing something, in terms of why this method would be better, assuming I can get the first issue fixed?

Would there be a way to move this into the main .js file and still have it render? I could move it into a dedicated .js file and call it after the content tag, but that messes with the asset pipeline and replaces four lines of embedded scripting with a call to another whole file.

Half the rails community would call this embedded scripting heretical but it just keeps looking like the most efficient solution.

Upvotes: 0

Views: 1069

Answers (2)

spitfire109
spitfire109

Reputation: 10039

Regarding your React-Rails component, it seems like you are simply missing the equals sign for the component to actually render.

Should be this:

<%= react_component('CommentBox', url: '/demo') %>

Instead, you have this:

<% react_component('CommentBox', url: '/demo') %>

Which doesn't actually render anything to the page with Rails.

Upvotes: 3

bratsche
bratsche

Reputation: 2674

If I simply move the above code into my main .js file, it loads before the content element exists and just renders nothing.

You can try doing something like:

document.addEventListener("DOMContentLoaded", function(event) {
  React.render(React.createElement(CommentBox, { url: '/demo' }),
               document.getElementById('content')
  );
});

I think whether the unobtrusive method is 'better' or not is kind of a subjective question. I'm still in the 'figuring out' stages of using React.js with Rails right now too and I haven't settled on what to do. I kind of like the unobtrusive style, but react_ujs.js depends upon everything being in the global namespace and I'm also experimenting with switching my asset management over to webpack/npm, and everything there is nicely modulized there (which overall I like, but it sucks for react_ujs).

Upvotes: 1

Related Questions