React on Rails integration
Asked Answered
V

1

9

I'm looking to implement ReactJS as the view of my Rails application with the gem react-rails. So far, I've only used the standard .erb to render my views in my RoR application and I am wondering some questions about how to do it with React.

For example, when you want to create a form for a model in RoR, you "just" create a form using :

<%= form_for(@product) do |f| %>
  <%= f.text_field :name %>
  ...
  <%= f.submit %>
<% end %>

And this automatically use the right route, generate the CSRF Token, use the right CSS id & class, etc...

Now, if I'm using React, I must take care of all of this ? And create form in JSX in the render, in the old fashioned way ?

# My view .html.erb
<%= react_component 'Form', {} %>

# My js.jsx file
var Form = React.createClass({
render: function () {
  return (
    <form className="new_my_model" onSubmit={this.handleSubmit}>
      <input style={inputStyle} type="text" className="my_model_name" />
      ...
      <input type="submit" value="Post" />
    </form>
  );
}
});

There is no "auto-generating feature" like Ruby for React ?

I've found some ressources online about tutorial for React & Rails (1, 2, 3) but most of the time they says different things. Some use JSX, some coffee, while the official React website recommend using JSX. Some use refs, others use states and it's like this with everything!

Is there a great tutorial that can be used as a reference for building the foundation of my application with React ?

Veljkov answered 25/7, 2015 at 16:6 Comment(1)
A lot has changed since this question was asked. Consider checking out github.com/shakacode/react_on_railsDonnydonnybrook
E
27

The short answer is that you write React components in JSX separated from the DOM elements written in the conventional views. React needs complete control over the DOM elements it manages to work well or you'll be fighting it the whole way (although limited use can be successful, it can be fragile).

At the risk that I'm not really answering what you mean to learn, here's a few thoughts that might help:

  • first, realize that ReactJS is still pretty young and integration with Rails even younger: best practices are still being discovered and decided so it's as much about picking a way and making it successful as it is about picking some best way.
  • second, hybrid techniques where concerns are not well separated are in general difficult to keep organized and managed in ways that are easily extensible. ReactJS is a view technique, so separating your view mechanics can become difficult if you try to mix approaches in unorganized ways, especially because of how ReactJS approaches DOM management. Also, you're working with the intersection of two disparate ecosystems and so support is thinner.
  • you have probably three main approaches:

    • minimal JS (using RoR in the classic way where JS augments the view,
    • moving the bulk of your views to ReactJS with minimal RoR view construction, and
    • separate service layers (using RoR to supply an API for AJAX use with a separate web service that presents the UI written in ReactJS (and so not integrate ReactJS directly into Rails)
  • there are undoubtedly many variations on these themes, but these are probably the main ones.

I've only worked on a couple of apps that do this, so take my comments with a grain of salt. Still, for new apps I tend toward the separate service layer approach because the tooling is so much easier. I tend to only use ReactJS in an existing app if I have a particularly JS-heavy part of a view and that functionality is well bounded.

Minimal ReactJS

In classic Rails views we tend to use JS just to augment the view with client side behavior: most of the view calculation is done server side and then we let JS just manipulate various aspects of the DOM for some targeted purposes. This can be difficult with React, because React takes responsibility for its elements of the DOM to keep the state updated. But you can still use ReactJS for elements of your page rather like you might a partial view render in Rails as long as that "partial" is well-bounded.

Using the React-Rails gem, just let your view render a React component as if you were going to use a partial and then let that component handle its constituent elements directly, using AJAX calls if you need more from the server during client use. This creates a limited, focused separation of concerns in your view and you can use the conventional JS techniques of gleaning other page DOM information that surrounds your component (though this can become difficult and chaotic if you do anything more than very limited forms of this -- probably ought to reconsider if you do much of that).

The main advantage of this approach is that you can begin to introduce ReactJS into an existing application and begin to migrate functionality as you find it useful. For certain client-side intensive things, like say a few form-fields with heavy client-side interaction, but that are well-bounded, this technique can be a good candidate.

ReactJS views from Rails

In this approach, we could use Rails to render the view layouts (i.e., the HTML wrapper but no content) and then let the specific views be either ReactJS-only or more conventional ERB/Haml/Slim views. In this approach, the Rails view would just establish a main React component for the page and then do the rest in ReactJS to manage that portion (usually the entire content pane) in it's own JSX. In this way, your JSX is still served from your asset pipeline, but really you've treated the core presentation of the page from React and just using Rails for the most minimal purposes of layouts and to allow some views to be ReactJS-based with others as Rails-based.

As I've described it, I'm rather assuming a multi-page app. If you're writing a single page app, this technique would probably just use Rails in a trivial way for presentation.

Still, there are some advantages:

  • again, you can mix and match techniques for different pages as a way to gradually introduce ReactJS into an app; say, as a way to convert some views over until all views are React-based. Then it's easier to move to the separate-service-layer approach if you want to.
  • you can still use the views to supply some information from the controller to the ReactJS components when first being rendered because your view will still initiate the React component. For any additional information once React is handling its sub-components, you'd still need to use AJAX (not really any different than any other JS functionality).
  • as you point out, Rails is still helping you with CSRF and those application-wide concerns.

Separate service layers

This approach divorces views from back-end service entirely. Write your Rails application to be an API server rendering JSON entirely. All the core logic is still handled in controllers and models so that portion of the design is largely intact. In fact, you don't need classic Rails for this. Other frameworks such as Grape or the rails-api gem might be more suitable because they're lighter-weight since you won't be rendering any views or needing those helpers.

Then you write a separate ReactJS based app (remember ReactJS can be server side too) that focuses only on presentation and just uses your RoR API service to get and post information.

Considerations to this approach:

  • you get a very clear separation of concerns: your Rails (or whatever) app focuses on the data/logic layer as a service and your ReactJS app focuses on presentation. There is a trend to using Rails more this way and you get another way to horizontally scale your application.
  • tooling is much easier since both are more homogeneous (automated testing alone is much easier). There is an established ecosystem around RoR and one around JS and ReactJS apps, but the intersection of those ecosystems is far sparser so you find yourself fighting the tooling more in the other two techniques. With separate layers, this isn't an issue.
  • works well for new applications, but probably much harder to convert an existing one (you have to both convert your controllers and your views at once).

Good luck!

UPDATE (9/2/2015) You may find this blog post illuminating: http://www.openmindedinnovations.com/blogs/3-ways-to-integrate-ruby-on-rails-react-flux by Blaine Hatab (3/2015). The post outlines three approaches that are somewhat similar to the high level outline I offered above, but are intended for a more complete picture of how to proceed. The three approaches they list are

  • Method 1: Use React inside of Rails with react-rails
  • Method 2: React/Flux front end app within Rails
  • Method 3: Separated Rails API and React/Flux front end app

You may find this description more useful and he offers references to see additional details.

Estate answered 25/7, 2015 at 19:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.