React integration with Rails

The easy way is not the best way

Rails are using Asset Pipeline which demands for all JS assets in the /app/assets directory (stored in repository)

Don't waste time for perfect tool

Find the tool that matches requirements

webpack as bundler, outputs to /app/assets 

How to use React components in Rails?

Use case overview

<%= react_component('inbox_wrapper', { messages: serialize_all(@messages) }) %>
import InboxWrapper from './components/inbox-wrapper';
registerComponent('inbox_wrapper', InboxWrapper);

Some Rails view rendered on server side:

Your main JS file that imports and register components (in webpack-bundled directory):

How does it work?

Generated files

We provide two main files that are worth mentioning

react_integration.js

view_helpers.rb

Included into Asset Pipeline and served as part of application js

Added as view helper to Rails application

How does it work?

Registering components

We expose global object called ReactRailsUJS

hidden from user (don't use it directly)

registerComponents (and couple more) works

on that global

How does it work?

Rendering in Rails

react_component helper renders DIV element with

proper name and props defined as data attributes

<div 
    data-react-class="inbox-wrapper" 
    data-react-props="{'messages':[
        {'body':'Test body #1','subject':'Test subject #1'},
        {'body':'Test body #2','subject':'Test subject #2'},
        {'body':'Test body #3','subject':'Test subject #3'}
    ]}">
</div>

How does it work?

Mounting components

react_integration.js is responsible for mounting components on DOMContentLoaded 

mountComponents: function(searchSelector) {
  var nodes = window.ReactRailsUJS._findDOMNodes(searchSelector);

  for (var i = 0; i < nodes.length; ++i) {
    var node = nodes[i];
    var className = node.getAttribute(window.ReactRailsUJS.CLASS_NAME_ATTR);
    var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR);
    (...)
    window.ReactRailsUJS.renderComponent(className, props, node);
    (...)
  }
}

Advantages

Node modules compliant

Basically seamless install

Router ready

Hot reload working with Rails ;)

How did we achieve hot reload?

We use react-hot-loader module with webpack-dev-server

We include assets from

webpack-dev-server that override

Asset Pipeline in development env

Road path

Server side rendering

More active users ;)

Seamless integration with Redux

Thanks!

Made with Slides.com