Extracting Data From Backbone Models

Below, we use a generic higher-order component to extract all attributes of a Backbone model into the state.We subscribe to the 'change' event (and unsubscribe on unmounting). When it happens, we update the state with the model's current attributes. Finally, if the model prop itself changes, we unsubscribe from the old model and subscribe to the new one.


RESETRUNFULL
function connectToBackboneModel(WrappedComponent) {
  return class BackboneComponent extends React.Component {
    constructor(props) {
      super(props);
      this.state = Object.assign({}, props.model.attributes);
      this.handleChange = this.handleChange.bind(this);
    }
    componentDidMount() {
      this.props.model.on('change', this.handleChange);
    }
    componentWillReceiveProps(nextProps) {
      this.setState(Object.assign({}, nextProps.model.attributes));
      if (nextProps.model !== this.props.model) {
        this.props.model.off('change', this.handleChange);
        nextProps.model.on('change', this.handleChange);
      }
    }
    componentWillUnmount() {
      this.props.model.off('change', this.handleChange);
    }
    handleChange(model) {
      this.setState(model.changedAttributes());
    }
    render() {
      const propsExceptModel = Object.assign({}, this.props);
      delete propsExceptModel.model;
      return <WrappedComponent {...propsExceptModel} {...this.state} />;
    }
  }}function NameInput(props) {
  return (<p><input value={props.firstName} onChange={props.handleChange} /><br />
                   My name is {props.firstName}.</p>
  );}const BackboneNameInput = connectToBackboneModel(NameInput);function Example(props) {
  function handleChange(e) {
    props.model.set('firstName', e.target.value);
  }
  return (<BackboneNameInput
  model={props.model}
                                               handleChange={handleChange}/>);}const model = new Backbone.Model({ firstName: 'Frodo' });ReactDOM.render(
  <Example model={model} />,
  document.getElementById('root'));