GithubHelp home page GithubHelp logo

goodanthony / react-rails Goto Github PK

View Code? Open in Web Editor NEW

This project forked from reactjs/react-rails

0.0 1.0 0.0 1.83 MB

Ruby gem for automatically transforming JSX and using React in Rails.

License: Apache License 2.0

Ruby 13.32% JavaScript 84.87% HTML 1.58% CoffeeScript 0.14% CSS 0.09%

react-rails's Introduction

Gem Build Status Gemnasium Code Climate Test Coverage


react-rails makes it easy to use React and JSX in your Ruby on Rails (3.2+) application. react-rails can:

Just getting started with React? Make sure to check out the [Getting Started] ( guide. If you're looking for a Webpack integrated method, see Related Projects below.


Add react-rails to your gemfile:

gem 'react-rails', '~> 1.6.0'

And install:

bundle install

Next, run the installation script:

rails g react:install

This will:

  • create a components.js manifest file and a app/assets/javascripts/components/ directory, where you will put your components

  • place the following in your application.js:

    //= require react
    //= require react_ujs
    //= require components


React.js builds

You can pick which React.js build (development, production, with or without add-ons) to serve in each environment by adding a config. Here are the defaults:

# config/environments/development.rb
MyApp::Application.configure do
  config.react.variant = :development

# config/environments/production.rb
MyApp::Application.configure do
  config.react.variant = :production

To include add-ons, use this config:

MyApp::Application.configure do
  config.react.addons = true # defaults to false

After restarting your Rails server, //= require react will provide the build of React.js which was specified by the configurations.

If you want to hand-pick which add-ons are added to your build they are available via sprockets directives.

//= require react
//= require react-addons-css-transition-group

react-rails offers a few other options for versions & builds of React.js. See for more info about using the react-source gem or dropping in your own copies of React.js.


After installing react-rails, restart your server. Now, .js.jsx files will be transformed in the asset pipeline.

react-rails currently ships with two transformers, to convert jsx code -

  • BabelTransformer using Babel, which is the default transformer.
  • JSXTransformer using JSXTransformer.js

You can use the deprecated JSXTransformer by setting it in an application config:

  config.react.jsx_transformer_class = React::JSX::JSXTransformer

BabelTransformer options

You can use babel's transformers and custom plugins, and pass options to the babel transpiler adding following configurations:

config.react.jsx_transform_options = {
  blacklist: ['spec.functionName', 'validation.react', 'strict'], # default options
  optional: ["transformerName"],  # pass extra babel options
  whitelist: ["useStrict"] # even more options

Under the hood, react-rails uses ruby-babel-transpiler, for transformation.

JSXTransformer options

You can use JSX --harmony or --strip-types options by adding a configuration:

config.react.jsx_transform_options = {
  harmony: true,
  strip_types: true, # for removing Flow type annotations
  asset_path: "path/to/JSXTransformer.js", # if your JSXTransformer is somewhere else

Rendering & mounting

react-rails includes a view helper (react_component) and an unobtrusive JavaScript driver (react_ujs) which work together to put React components on the page. You should require the UJS driver in your manifest after react (and after turbolinks if you use Turbolinks).

The view helper puts a div on the page with the requested component class & props. For example:

<%= react_component('HelloMessage', name: 'John') %>
<!-- becomes: -->
<div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>

On page load, the react_ujs driver will scan the page and mount components using data-react-class and data-react-props.

If Turbolinks is present components are mounted on the page:change event, and unmounted on page:before-unload. Turbolinks >= 2.4.0 is recommended because it exposes better events.

The view helper's signature is:

react_component(component_class_name, props={}, html_options={})
  • component_class_name is a string which names a globally-accessible component class. It may have dots (eg, "MyApp.Header.MenuItem").
  • props is either an object that responds to #to_json or an already-stringified JSON object (eg, made with Jbuilder, see note below).
  • html_options may include:
    • tag: to use an element other than a div to embed data-react-class and data-react-props.
    • prerender: true to render the component on the server.
    • **other Any other arguments (eg class:, id:) are passed through to content_tag.

Server rendering

To render components on the server, pass prerender: true to react_component:

<%= react_component('HelloMessage', {name: 'John'}, {prerender: true}) %>
<!-- becomes: -->
<div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}">
  <h1>Hello, John!</h1>

(It will also be mounted by the UJS on page load.)

There are some requirements for this to work:

  • react-rails must load your code. By convention it uses components.js, which was created by the install task. This file must include your components and their dependencies (eg, Underscore.js).

  • Your components must be accessible in the global scope. If you are using files then the wrapper function needs to be taken into account:

    # @ is `window`:
    @Component = React.createClass
      render: ->
        `<ExampleComponent videos={this.props.videos} />`
  • Your code can't reference document. Prerender processes don't have access to document, so jQuery and some other libs won't work in this environment :(

You can configure your pool of JS virtual machines and specify where it should load code:

# config/environments/application.rb
# These are the defaults if you dont specify any yourself
MyApp::Application.configure do
  # Settings for the pool of renderers:
  config.react.server_renderer_pool_size  ||= 1  # ExecJS doesn't allow more than one on MRI
  config.react.server_renderer_timeout    ||= 20 # seconds
  config.react.server_renderer = React::ServerRendering::SprocketsRenderer
  config.react.server_renderer_options = {
    files: ["react-server.js", "components.js"], # files to load for prerendering
    replay_console: true,                 # if true, console.* will be replayed client-side
  • On MRI, use therubyracer for the best performance (see discussion)
  • On MRI, you'll get a deadlock with pool_size > 1
  • If you're using JRuby, you can increase pool_size to have real multi-threaded rendering.

You can configure camelize_props option and pass props with an underscored hash from rails but get a camelized hash in jsx :

MyApp::Application.configure do
  config.react.camelize_props = true #default false

Rendering components instead of views

Components can also be prerendered directly from a controller action with the custom component renderer. For example:

class TodoController < ApplicationController
  def index
    @todos = Todo.all
    render component: 'TodoList', props: { todos: @todos }, tag: 'span', class: 'todo'

This custom renderer behaves the same as a normal view renderer and accepts the usual arguments - content_type, layout, location and status. By default, your current layout will be used and the component, rather than a view, will be rendered in place of yield. Custom data-* attributes can be passed like data: {remote: true}.

Component generator

react-rails ships with a Rails generator to help you get started with a simple component scaffold. You can run it using rails generate react:component ComponentName (--es6). The generator takes an optional list of arguments for default propTypes, which follow the conventions set in the Reusable Components section of the React documentation.

For example:

rails generate react:component Post title:string body:string published:bool published_by:instanceOf{Person}

would generate the following in app/assets/javascripts/components/post.js.jsx:

var Post = React.createClass({
  propTypes: {
    title: React.PropTypes.string,
    body: React.PropTypes.string,
    published: React.PropTypes.bool,
    publishedBy: React.PropTypes.instanceOf(Person)

  render: function() {
    return (
        <div>Title: {this.props.title}</div>
        <div>Body: {this.props.body}</div>
        <div>Published: {this.props.published}</div>
        <div>Published By: {this.props.publishedBy}</div>


--es6 : Generate the same component but using cutting edge es6 class

For example:

rails generate react:component Label label:string --es6

--coffee : Generate the component using CoffeeScript syntax

For example:

rails generate react:component Label label:string --coffee


The generator can use the following arguments to create basic propTypes:

  • any
  • array
  • bool
  • element
  • func
  • number
  • object
  • node
  • shape
  • string

The following additional arguments have special behavior:

  • instanceOf takes an optional class name in the form of {className}.
  • oneOf behaves like an enum, and takes an optional list of strings in the form of 'name:oneOf{one,two,three}'.
  • oneOfType takes an optional list of react and custom types in the form of 'model:oneOfType{string,number,OtherType}'.

Note that the arguments for oneOf and oneOfType must be enclosed in single quotes to prevent your terminal from expanding them into an argument list.

Jbuilder & react-rails

If you use Jbuilder to pass a JSON string to react_component, make sure your JSON is a stringified hash, not an array. This is not the Rails default -- you should add the root node yourself. For example:

# BAD: returns a stringified array
json.array!(@messages) do |message|
  json.extract! message, :id, :name
  json.url message_url(message, format: :json)

# GOOD: returns a stringified hash
json.messages(@messages) do |message|
  json.extract! message, :id, :name
  json.url message_url(message, format: :json)


It is possible to use JSX with CoffeeScript. To use CoffeeScript, create files with an extension We also need to embed JSX code inside backticks so that CoffeeScript ignores the syntax it doesn't understand. Here's an example:

Component = React.createClass
  render: ->
    `<ExampleComponent videos={this.props.videos} />`

Alternatively, the newer ES6 style class based syntax can be used like this:

class Component extends React.Component
  render: ->
    `<ExampleComponent videos={this.props.videos} />`

Extending react-rails

You can extend some of the core functionality of react-rails by injecting new implementations during configuration.

Custom Server Renderer

react-rails depends on a renderer class for rendering components on the server. You can provide a custom renderer class to config.react.server_renderer. The class must implement:

  • #initialize(options={}), which accepts the hash from config.react.server_renderer_options
  • #render(component_name, props, prerender_options) to return a string of HTML

react-rails provides two renderer classes: React::ServerRendering::ExecJSRenderer and React::ServerRendering::SprocketsRenderer.

ExecJSRenderer offers two other points for extension:

  • #before_render(component_name, props, prerender_options) to return a string of JavaScript to execute before calling React.render
  • #after_render(component_name, props, prerender_options) to return a string of JavaScript to execute after calling React.render

Any subclass of ExecJSRenderer may use those hooks (for example, SprocketsRenderer uses them to handle console.* on the server).

Custom View Helper

react-rails uses a "helper implementation" class to generate the output of the react_component helper. The helper is initialized once per request and used for each react_component call during that request. You can provide a custom helper class to config.react.view_helper_implementation. The class must implement:

  • #react_component(name, props = {}, options = {}, &block) to return a string to inject into the Rails view
  • #setup(controller_instance), called when the helper is initialized at the start of the request
  • #teardown(controller_instance), called at the end of the request

react-rails provides one implementation, React::Rails::ComponentMount.

Custom JSX Transformer

react-rails uses a transformer class to transform JSX for the browser. The transformer is initialized once, at boot. You can provide a custom transformer to config.react.jsx_transformer_class. The transformer must implement:

  • #initialize(options), where options is the value passed to config.react.jsx_transform_options
  • #transform(code_string) to return a string of transformed code

react-rails provides two transformers, React::JSX::JSXTransformer and React::JSX::BabelTransformer.

Related Projects

  1. react_on_rails Gem: Webpack Integration of React with Rails utilizing the modern JavaScript tooling and libraries, including Webpack, Babel, React, Redux, React-Router. You can an example of this live at
  2. React.rb: Use Ruby to build reactive user interfaces with React under the covers.github source code here.

react-rails's People


alg avatar andreamaggi avatar andreynering avatar andygeers avatar aratak avatar arbmind avatar benpickles avatar bensie avatar borisrorsvort avatar byroot avatar christopherstyles avatar danott avatar eugenijusr avatar frantic avatar grahamcracker avatar hartator avatar jtmalinowski avatar lifeiscontent avatar meleyal avatar olance avatar quark-zju avatar rmosolgo avatar robrobbins avatar sjltaylor avatar tricknotes avatar vipulnsward avatar ximus avatar xionon avatar zhanghandong avatar zpao avatar



Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.