React on Rails

Vipul A M

@vipulnsward

😓

 

http://rubyconfindia.org/

 

http://www.gardencityruby.org/

 

http://www.deccanrubyconf.org/

Part 1-React

Build UI

V in MVC

Simple

Virtual DOM

Components

Props/State

Re-Render 💥

JSX

// Using JSX to express UI components.
var dropdown =
  <Dropdown>
    A dropdown list
    <Menu>
      <MenuItem>Do Something</MenuItem>
      <MenuItem>Do Something Fun!</MenuItem>
      <MenuItem>Do Something Else</MenuItem>
    </Menu>
  </Dropdown>;

render(dropdown);
var App = React.createClass({  

  getInitialState: function() { 
    return {name: 'Vipul'};
  },
  
  render: function() { 
    console.log(this.props)
    return <h1>{this.state.name}</h1>
  }
  
});


React.render(<App name='Vipul'/>, document.body);

Life-Cycle

console.log('Start')
var App = React.createClass({
    componentWillMount: function(){
      console.log('componentWillMount');
    },
    
    componentDidMount: function(){
      console.log('componentDidMount');
    },
    
    getInitialState: function(){
      return { status: true}
    },

    getDefaultProps: function(){
      return {name: 'John'};
    },
  
    componentWillReceiveProps: function(nextProps){
      console.log('componentWillReceiveProps');
    },

    shouldComponentUpdate: function(nextProps, nextState){
      console.log('shouldComponentUpdate');
      return true;
    },
    
    componentWillUpdate: function(){
      console.log('componentWillUpdate');
    },
    
    render: function() {
      console.log('render');
      return <h1 onClick={this.toggleState}>    
             {this.state.status.toString()}
             </h1>
    },

    componentWillUnmount: function(){
      console.log('componentWillUnmount')
    },
    
    toggleState: function() {
      this.setState({status: !this.state.status})
    }
    });

...
    shouldComponentUpdate: function(nextProps, nextState){
      console.log('shouldComponentUpdate');
      return true;
    },
    
    componentWillUpdate: function(){
      console.log('componentWillUpdate');
    },
    
    render: function() {
      console.log('render');
      return <h1 onClick={this.toggleState}>    
             {this.state.status.toString()}
             </h1>
    },

    componentWillUnmount: function(){
      console.log('componentWillUnmount')
    },
    
    toggleState: function() {
      this.setState({status: !this.state.status})
    }
    });

Multiple Components

var FruitsList = React.createClass({
    render: function () {
        return <div>
        <h1>{this.props.name}</h1>
        <ul>
        <li>Apple</li>
        <li>Orange</li>
        <li>Banana</li>
        </ul>
        </div>
    }
});


var App = React.createClass({
    render: function () {
        return <div>
        <FruitsList name='Fruits'/>
        </div>
    }
});


React.render(<App/>, document.body);

Events and forms

...
          <form onSubmit={::this.submitPost}>

            <div className="form-group">
              <textarea className="form-control"
                        placeholder="Title"
                        value={this.state.title}
                        onChange={(event) => this.handleChange(event, 'title')}/>
            </div>

...
            <div className="form-group">
              <button type="submit"
                      ref="submit"
                      className="btn btn-success">
                Submit
              </button>
            </div>
          </form>

...


  handleChange(event, attribute) {
    var newState = this.state;
    newState[attribute] = event.target.value;
    newState.errors = null;
    this.setState(newState);
    console.log(this.state);
  }

...

Part 2-React-Rails

+

=






// Gemfile
gem 'react-rails', '~> 1.0'

// Install
rails g react:install


// Inside application.js
//= require react
//= require react_ujs
//= require components
rails generate react:component Post title:string 
body:string 
published:bool 
published_by:instanceOf{Person}


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>
        <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>
      </div>
    );
  }
});








<%= react_component('HelloMessage', {name: 'John'}, {prerender: true}) %>


<!-- becomes: -->
<div data-react-class="HelloMessage" 
data-react-props="{"name":"John"}">
  <h1>Hello, John!</h1>
</div>


// From ActiveRecord

<%= react_component('Posts', posts: @posts) %>

Text

// variables
const a=10; let b = 10;

//arrow functions
odds = evens.map(v => v  +1 )

// Spread Operators
let str = "foo"
let chars = [ ...str ] // [ "f", "o", "o" ]

// String Interpolation
message = `Hello ${customer.name}`


// Classes!
class Shape {
    constructor (id, x, y) {
        this.id = id
        this.move(x, y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

Demo




  submitPost(event) {
    event.preventDefault();

    fetch('/posts', {
      method: 'post',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({post: this.state})
    }).then(::this.parseJSON)
      .then(::this.setPosts)
      .catch(function (ex) {
      console.log('parsing failed', ex)
    });

  }

Flux

Redux

gem react_on_rails

webpack

​@vipulnsward

bigbinary.com/videos

https://github.com/shakacode/react_on_rails

https://github.com/vipulnsward/react-rails-browserify

Vipul A M

@vipulnsward

@bigbinary

React on Rails Rubyconf Taiwan 2015

By Vipul Amler

React on Rails Rubyconf Taiwan 2015

React on Rails Rubyconf Taiwan 2015

  • 3,714