Why I’m using React with Rails

I've been using Rails for years and recently I’ve been integrating javascript frameworks into my stack in various ways to help with front end development. There are a lot of great javascript frameworks out there like Angular, Ember, Meteor, etc, but my current favorite is React and Flux. Facebook has been doing tremendous work open sourcing their javascript stack from Instagram and Facebook with tools like React, Flux, React Native, and Relay. The details behind all of those are pretty ridiculous, but I encourage you to check all of it out on their YouTube channel and React website. I’m going to focus on Flux and React in this blog, but I’d recommend these videos if you’re interested in learning about React Native and Relay, https://www.youtube.com/watch?v=KVZ-P-ZI6W4 and https://www.youtube.com/watch?v=9sc8Pyc51uU. They are really exciting libraries that will extend the already awesome React ecosystem.

React is fairly simple to get going with, but there are actually a lot of high level reasons why it is so great. It promotes events and data to be one directional constraining your development process in a good way, it leverages the virtual DOM for high performance, promotes componentized development, and is just a view layer helping to make it more modular. Now comparing React to the other frameworks isn’t fair because they are full MVC, but this is where Flux comes in. Flux is actually more of a concept than a framework and there are of Flux implementations right now, but its core principal of one directional data flow lines up with React nicely.

Enough about React!! Show me how to integrate it with Rails.

Method 1: Use React inside of Rails with react-rails

This is probably the simplest method for a Rails developer and the first thing you’ll find when Googling react and rails. There is a gem called react-rails, https://github.com/reactjs/react-rails, that gives you a handy view helper that lets you render (and server render) react components in rails views. You define your data in the Rails controller, pass it into the view helper, and it passes the data as props to the React component. It’s super simple to get going, just follow their readme and you’ll be able to get a react component in your rails views easily.

You can use either active model serializer or jbuilder to convert your data to json and you’ll be good to go in no time. Now the main reason to use this setup is you get to fully leverage your rails ecosystem and server render react easily. I mainly did this because I wanted to still use Rails for forms and authentication (devise), but I wanted react for my more dynamic pages. It works great and I can easily switch from a regular rails view for a form to a show page with React and jbuilder. I’d also recommend this blog that shows you how to setup role based authorization with this setup too, http://blog.littleblimp.com/post/109540707808/role-based-authorization-with-react-js. I found this very useful.

Here’s some sample code

# app/views/users/show.html.slim = react_component ( 'UserShowPage' , render ( template: 'users/show.json.jbuilder' ))

# app/views/users/show.json.jbuilder json . user do json . extract ! ( @user , : id , : email , : description , : github ) end json . projects @user . projects , partial: 'projects/project' , as: : project

# app/controllers/users_controller.rb def show @user = User . find ( params [ :id ] ) end

# app/assets/javascripts/components/users/user_show_page.js.cjsx window . UserShowPage = React . createClass render: -> < div > < ul className = 'list-unstyled' > < li > < b > Email: </ b > { @props . user . email } </ li > < li > < b > Description: </ b > { @props . user . description } </ li > < li > < b > Github: </ b > { @props . user . github } </ li > </ ul > < h3 > { @props . user . email + "'s Projects" } </ h3 > < ProjectList projects = { @props . projects } /> </ div >

Pros and Cons

Pretty simple to get going, but my biggest complaint is that I have to define my data on the rails side for server rendering. I would prefer to make my api calls on the javascript side and ignore the ajax call using flux if the data is already in the store. This also keeps my view specific data needs in the right place. I want the data needed for a specific view to be defined in that view code. I’m sure setting this up with react-rails is possible, but it seemed like a mountain not worth climbing. If you want to leverage server sider rendering with react-rails, you really should just pass data into the view helper.

Method 2: React/Flux front end app within Rails

This is one of the more interesting stacks and credit goes to Justin Gordon for building a template. You should check out his blog and github code for more details, https://github.com/justin808/react-webpack-rails-tutorial and http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/.

Now what he does is actually pretty beautiful. He has webpack compile all of the assets in the webpack folder and feed the bundle file into the rails asset pipeline. You still get to use things like turbolinks, rails gems, and all that jazz while separating your front end out into a separate eco system. He also set it up so you can easily leverage npm modules and use ES6 (which is great). He didn’t actually set this up with Flux yet, but the asset configuration is there and getting flux in there would be simple because you could take most standalone Flux apps and put it into his setup. He is actually in the works on setting it up with Flux too.

Pros and Cons

My favorite part about this setup is how it completely separates out the front end so it feels like a complete javascript app. The first setup is more like putting components inside of your rails app, while this is feeding a javascript MVC into your rails asset pipeline.

The problem I encountered was setting up server rendering, which wasn’t an issue for him. I tried to take his setup and get server rendering going with react-rails, but it started to take away from the beauty of it because I would have had to start defining data on the controllers and rails views. Then you’ve kind of broken the separation of your front end and back end by doing this. You might be able to do something fancy with react router and rendering a single page that passes different data in using the rails router, but this was another mountain I didn’t want to climb. I would definitely recommend this stack if you want to use Flux + React but keep it within a rails app for easy development.

Method 3: Separated Rails API and React/Flux front end app

This setup is conceptually simple and just involves a Rails API serving data up to a separate node app with Flux and React. You can follow any tutorials out there on building a Rails API, which will most likely leverage rails-api. https://github.com/rails-api/rails-api. Then you can follow any Flux/React tutorial that shows you how to make a standalone app and just call your Rails API for data. Egghead.io has a great set of tutorials guiding you all the way through making a Flux app.

I would highly recommend this blog if you go down this route, http://fancypixel.github.io/blog/2015/01/28/react-plus-flux-backed-by-rails-api/. They cover a lot of key concepts of getting a Rails API setup with a Flux app.

Pros and Cons

Keeping the two apps is nice conceptually, but it really makes the development process cumbersome. You’re going to be maintaining a Rails API on a server and a node app on another server if you want server rendering. If you don’t actually need server rendering, it does get simpler because you can just host on any standard web server, but it’s nice to be able to leverage server rendering if needed. If you don’t need server rendering, then I would just recommend setup two and keep your javascript app inside of your Rails app.

Conclusion

Overall I found that React being a view only library makes it easy to set it up in whatever way you need, and you have some good options depending on what your app calls for. You can easily put some React in your rails app with react-rails or go with a more complete setup with Flux inside of your Rails app or separated out.

Most of the exploration I was doing was in pursuit of a perfect stack that kept data calls in my javascript side, server rendered easily, and keep it all in one nice app. This wasn’t perfectly attainable in one setup, but I think more options will start to develop in time.

PS. Regarding Flux implementations, there are a lot out there but my current favorite is Alt. https://github.com/goatslacker/alt. I thought it was easier to reason about than the default Flux implementation and it uses ES6.

And if you are interested in defining your data in your components and can’t wait for Relay, check out this library. https://github.com/ericclemmons/react-resolver.

There's also a great community for flux and react on slack. Just go sign up here, http://reactiflux.com/.