On Github sq0032 / react-integration-strategy
Created by Ping-Wen (Mark) Hsu
2015/11/10 for ReactJS Waterloo
The reason I choose Backbone is because this is what I'm currently working on. I tried AngularJs, but it's not making live easier. Just want to share how I did the change.If you app structure looks like this:
I'm sorry about that
React or my strategy neither a medicine that cures all the diseases.If looks like this:
Fine, you can stay :-)
Example
View
                        
//view.js
views.ItemView = Backbone.View.extend({
    events:{
        'click .toggle': 'toggleCompleted',
    },
    initialize:function{
        this.listenTo(this.model, 'change', this.render);
    },
    render:function(){
        var itemHTML = _.template(item_html)({
            item: this.model 
        });
        this.$el.html(itemHTML);
    },
    toggleCompleted:function(event){
        this.model.toggle();
    }
});
                        
                    
                   Template
                            
<!-- Template -->
<div class="view">
    <input class="toggle" type="checkbox" <%= item.get("completed") ? 'checked': '' %>>
    <label><%= item.get("title") %></label></label>
    <button class="destroy"></button>
</div>
                        
                    
                    Step 1: Make a HTML render machine
                            
class Item extends React.Component{
  render(){
    const { item } = this.props;
    return (
        <div className="view>
            <input className="toggle" type="checkbox" item.get("completed") ? 'checked': '' />
            <label>item.get("name")</label>
            <button className="destroy"></button>
        </div>
    );
  }
}
                            
                        
                                                
<!-- Template -->
<div class="view">
    <input class="toggle" type="checkbox" <%= item.get("completed") ? 'checked': '' %>>
    <label><%= item.get("title") %></label></label>
    <button class="destroy"></button>
</div>
                            
                        
                                                    
//Component.render()
const { item } = this.props;
return (
    <div className="view">
        <input className="toggle" type="checkbox" item.get("completed") ? 'checked': '' />
        <label>item.get("name")</label>
        <button className="destroy"></button>
    </div>
);
                            
                                                
                    Then modify view render function
                            
//view.js
views.ItemView = Backbone.View.extend({
    render:function(){
        //before
        var itemHTML = _.template(item_html)({
            item: this.model 
        });
        this.$el.html(itemHTMLitemHTML);
        
        //after
        React.render(
            <Item item={this.model} />,
            this.$el
        );
    },
});
                            
                        
                    Step 2: Write events handler
This slide has fragments which are also stepped through in the notes window.2-1: Create a click handler
                            
class Item extends React.Component{
  handleToggle(){
    this.props.toggleCompleted();
  }
  render(){
    const { item } = this.props;
    return (
        <div className="view>
            <input className="toggle" 
                      type="checkbox" 
                      item.get("completed") ? 'checked': '' 
                      onClick={this.handleToggle.bind(this)}/>
            <label>item.get("name")</label>
            <button className="destroy"></button>
        </div>
    );
  }
}
                            
                        
						
							Create a click handler, and call the function that pass in as a prop.
						2-2: Pass the view function into the component
                        
//view.js
views.ItemView = Backbone.View.extend({
//    events:{
//        'click .toggle': 'toggleCompleted',
//    },
    initialize:function{
        this.listenTo(this.model, 'change', this.render);
    },
    render:function(){
        React.render(
            <Item item={this.model} toggleCompleted={toggleCompleted} />,
            this.$el
        );        
    },
    toggleCompleted:function(event){
        this.model.toggle();
    }
});
                        
                    
                    
                        Now you start taking benefit from React by simplifing event transmition procesure.
                        Some people would add/remove classname here which you don't need it with React. Just put the logic into the component's render function. 
                    Step 3: Replace Backbone View
This part is tricky one, cuz here is the place you need to make a desision.A question needs to be answer:
Is the model only be used by the current view/component?
If yes, keep using model as a prop
                            
class Item extends React.Component{
  handleToggle(){
    this.model.toggle();
  }
  render(){
    const { item } = this.props;
    return (
        <div className="view>
            <input className="toggle" 
                      type="checkbox" 
                      item.get("completed") ? 'checked': '' 
                      onClick={this.handleToggle.bind(this)}/>
            <label>item.get("name")</label>
            <button className="destroy"></button>
        </div>
    );
  }
}                            
                            
                        
                        
							The mutation happens in a parent component
						If no, use states instead
                            
class Item extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      model: this.props.model,
    };
  }
  handleToggle(){
    this.state.model.toggle();
    this.setState({model:this.model});
  }
  render(){
    const item = this.state.model;
    return (
        <div className="view>
            <input className="toggle" 
                      type="checkbox"
                      item.get("completed") ? 'checked': '' 
                      onClick={this.handleToggle.bind(this)}/>
            <label>item.get("name")</label>
            <button className="destroy"></button>
        </div>
    );
  }
}                            
                            
                        
                        
							This model is the single source of truth.
						                          
//ListView.js
views.ListView = Backbone.View.extend({
  render:function(){
    var Items = this.collections.map(function(item){
      return (
        <Item item={item}
              //Pass function if ListView is in charge of data mutating
              toggleCompleted={toggleCompleted}
              key={item.get("id")}/>
      );
    });
    React.render(
      Items,
      this.$el
    ); 
  },
});
                          
                      					  
					Step 4: Apply internal Flux by features
This part is tricky one, cuz here is the place you need to make a desision.Can I still use third-party libraries?
You can use those:
You can't use those: