Porting a Rails frontend from CoffeeScript to ES6 and JSX – examples

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

We are working on a new version of our bestseller book – Rails meets React.js. Currently, the book is based in CoffeeScript and we want to port it to ES6. The update will be free for everyone, who bought the CoffeeScript version

Here are some examples showing a process of porting from CoffeeScript to ES6 and JSX.

JSX

In our previous version of this book, we didn’t use JSX because it does not fit well with CoffeScript. With ES6 it is different, JSX fits here very well.

Before:

  Stats = React.createClass     contextTypes:       user: React.PropTypes.object     render: ->       React.DOM.div null,         "Won: #{@context.user.won}"         React.DOM.br null         "Lost: #{@context.user.lost}"         React.DOM.br null         React.DOM.a           href: "http://www.example.org/stats/#{@context.user.id}",           "(see the whole stats of #{@context.user.name})"    stats = React.createFactory(Stats) 

After:

class Stats extends React.Component {   render() {     return (       <div>         Won {this.context.user.won}         <br />         Lost {this.context.user.lost}         <br />         <a href={`http://www.example.org/stats/${this.context.user.id}`} >           (see the whole stats of {this.context.user.name})         </a>       </div>     );   } } 

Note ES6 template literal `http://www.example.org/stats/${this.context.user.id}` which we are using to construct string url.

ES6 classes

Instead of using React.createClass we are now using ES6 class syntax:

Before:

OneTimeClickLink = React.createClass   render: ->     React.DOM.div(       {id: "one-time-click-link"},       React.DOM.a(         {href:"javascript:void(0)"},         "Click me"       )     ) 

After:

class OneTimeClickLink extends React.Component {   render() {     return (<div id="one-time-click-link">       <a href="javascript:void(0)">         Click me       </a>     </div>);   } 

State initialization

Since getInitialState does not work with classes syntax, we are initializing state in a constructor. Like in this example:

Before:

DateWithLabel = React.createClass   getInitialState: ->     date: new Date()   render: ->     DOM.div 

After:

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

class DateWithLabel extends React.Component {   constructor(props) {     super(props);     this.state = {       date: new Date()     };   }    render() {     return (<div></div>);   } } 

Bind instance methods

In class syntax, React doesn’t bind all methods automatically. So, we are binding them in our constructor.

Before:

  OnOffCheckbox = React.createClass     getInitialState: ->       toggled: false      toggle: ->       @setState toggled: !@state.toggled      render: ->       React.DOM.input         key: 'checkbox'         type: 'checkbox'         id: @props.id         checked: @state.toggled         onChange: @toggle  

After:

  class OnOffCheckbox extends React.Component {     constructor(props) {       super(props);       this.state = {         toggled: false       };       this.toggle = this.toggle.bind(this);     }      toggle() {       this.setState({ toggled: !this.state.toggled });     }      render() {       return (         <input           key="checkbox"           type="checkbox"           id={this.props.id}           checked={this.state.toggled}           onChange={this.toggle}         />       );     }   }  

Default props and validations

defaultProps , propTypes and contextTypes must be defined outside the class body. Here are some examples:

Before:

  OnOffCheckbox = React.createClass     getDefaultProps: ->       initiallyToggled: false      getInitialState: ->       toggled: @props.initiallyToggled      toggle: ->       @setState toggled: !@state.toggled      render: ->       React.DOM.input         key: 'checkbox'         type: 'checkbox'         id: @props.id         checked: @state.toggled         onChange: @toggle 

After:

  class OnOffCheckbox extends React.Component {     constructor(props) {       super(props);       this.state = {         toggled: props.initiallyToggled       };       this.toggle = this.toggle.bind(this);     }      toggle() {       this.setState({ toggled: !this.state.toggled });     }      render() {       return (         <input           key="checkbox"           type="checkbox"           id={this.props.id}           checked={this.state.toggled}           onChange={this.toggle}         />       );     }   }   OnOffCheckboxWithLabel.defaultProps = {     initiallyToggled: false   };  

The same goes for propTypes:

Before:

Blogpost = React.createClass   propTypes:     name: React.PropTypes.string.isRequired    # ... 

After:

class Blogpost extends React.Component {   // ... } Blogpost.propTypes = {   name: React.PropTypes.string.isRequired }; 

Summary

Code written in ES6 with JSX can be pretty clean. I’ve used ESLint which helped me to keep syntax clean and free of errors. Here you can find a Blogpost how correctly configure it for your editor.

If you are interested in learning how to use React with Rails, with the ES6 syntax, we are working on a new version of Rails meets React.js. It will be free for everyone who bought previous CoffeeScript version.

Leave a Reply

Your email address will not be published. Required fields are marked *