Getting Started With React.js and Rails
Why use React.js?
- React ~35kb vs. Amber.js ~100kb
- Easy to learn compared to Ember.js and Angular.js
- Supports server-side rendering
- Great performance
- Angular.js documentation is horrible
- Angular.js is the new EJB
Why shouldn't you use React.js?
- React.js is difficult to integrate with JS libraries that move or create DOM elements, e.g. jQuery UI
- React.js is still evolving. Expect API changes to break your app.
Installation
Gemfile:
gem 'active_model_serializers' # You probably want this gem too...
gem 'react-rails', '~> 1.0.0.pre', github: 'reactjs/react-rails'
From the console run:
bundle
rails g react:install
Make sure you have this in app/assets/javascript/application.js:
# ...
#= require react
# For the <div data-react-class...> syntax
#= require react_ujs
#= require_tree components
Add this to config/environments/production.rb
Rails.config.react.variant = :production
And this to config/environments/development.rb
Rails.config.react.variant = :development
Hello World
Create app/assets/javascripts/components/hello.jsx.coffee (note the file extension):
###* @jsx React.DOM ###
window.Hello = React.createClass
render: ->
<div>{this.props.name}</div>
app/views/layouts/application.html.erb
<html>
…
<div data-react-class="Hello" data-react-props=<%= { name: 'John' }.to_json %>/>
or:
<%= react_component 'Hello', name: 'John' %>
....
</html>
Troubleshooting
- Unexpected token '<' Error
Did you forget to add this to the top of your React component file (.js.jsx)?
/** @jsx React.DOM */
or this to your CoffeeScript component (.jsx.coffee):
###* @jsx React.DOM ###
- Target container is not a DOM element.
Does the DOM element exist?
Did you forget to call React.renderComponent in jQuery’s $(document).ready?
- Adjacent XJS elements must be wrapped in an enclosing tag
Multiple nodes need a parent element:
<ul> // Doesn't work without <ul> wrapper
<li></li>
<li></li>
</ul>
- Still doesn’t work?
react-rails is not stable; expect it to break.
Gotchas
- The only way to get a handle to a React Component instance outside of React is by storing the return value of React.renderComponent: http://facebook.github.io/react/docs/component-api.html
- Integration with e.g. Bootstrap is not trivial and will break when APIs change: https://github.com/facebook/react/blob/master/examples/jquery-bootstrap/js/app.js
Solutions: React.js Google Group React.js and jQuery sortable React.js and select2 React.js and Bootstrap Modal React.js and Kendo UI
- You need to change the HTML "class" attribute to "className" in JSX