--- layout: post title: "Using React components as Backbone Views" author: Thomas Boyt --- *This post was originally published at [thomasboyt.com](http://thomasboyt.com).* At Venmo, we've begun rewriting and redesigning our front-end into clean, idiomatic Backbone code. Backbone is an unopinionated framework that provides structure to your code. However, its view layer is purposefully lacking, providing only a few basic lifecycle hooks. Unlike Ember components or Angular directives, it does not hook your data up to your views for you, and does little to enforce separation between your layers. While we've gotten surprisingly far using only vanilla Backbone views, we've begun exploring more advanced options for architecting our UI. My goal was to find something that could interface with Backbone views that gave me the data binding and scoping that I was used to from views in larger frameworks. Thankfully, my friend [Scott](https://scott.mn/) pointed me at React, and after a few hours of wrestling with it, I came away very impressed. ## Overview [React](http://facebook.github.io/react/) is a relatively new library by Facebook for creating *isolated components*. In many ways, it's similar to Angular directives or Polymer web components. A React component is essentially a custom DOM element with its own scope. It cannot directly interact with other portions of your application's state, whether in JavaScript or in the DOM. The most unique - and most controversial - part of React is its use of JSX, which transforms HTML written inline with your code into parseable JavaScript. Here's an example React component that uses JSX to render a link: {% highlight javascript %} /** @jsx React.DOM */ var component = React.createClass({ render: function() { return Venmo } }); {% endhighlight %} This gets transformed into: {% highlight js %} /** @jsx React.DOM */ var component = React.createClass({ render: function() { return React.DOM.a( {href:"http://venmo.com"}, "Venmo") } }); {% endhighlight %} Integrating JSX with your workflow is easy, thanks to the plethora of tools for compilation: * [require-jsx](https://github.com/seiffert/require-jsx), is a RequireJS plugin for loading JSX files * [reactify](https://github.com/andreypopp/reactify) is a Browserify transform for JSX files * [grunt-react](https://github.com/ericclemmons/grunt-react) compiles JSX files through Grunt *JSX is optional* - you can write your templates using the `React.DOM` DSL if you'd like, though I'd only recommend this for simple templates. Instead of teaching the basics of React in this post, I'll pass that responsibility to the [excellent React tutorial](http://facebook.github.io/react/docs/tutorial.html). It's a bit long, but give it a skim before continuing! ## Rendering a component from a Backbone view Let's create a very basic component: a link that fires an event when clicked. We'd like to render this component as part of a Backbone view, rather than use it on its own. The component is easy enough to create: {% highlight js %} var MyWidget = React.createClass({ handleClick: function() { alert('Hello!'); }, render: function() { return ( Do something! ); } }); {% endhighlight %} This is almost the same as the above example, except for the addition of a `handleClick` handler for the link's click event. Now, all we need to do is add a Backbone View to render this in: {% highlight js %} var MyView = Backbone.View.extend({ el: 'body', template: '
', render: function() { this.$el.html(this.template); React.renderComponent(new MyWidget(), this.$('.widget-container').get(0)); return this; } }); new MyView().render(); {% endhighlight %} Here's our completed new component: ## Component -> Backbone communication Of course, to really take advantage of React components, we'll need to be communicate changes from React to Backbone. For a very arbitrary example, let's say that we want to display a bit of text if the link in our component has been clicked. Not only that, but we want the bit of text to be *outside* the component's DOM element. While the React docs are very good at explaining how to have different components communicate, it's not super obvious how a child component could interact with a parent Backbone view. However, there's a single, easy way to communicate: we can bind an event handler through the component's properties. Here's an example of this pattern, in JSX: {% highlight js %} function anEventHandler() { ... } React.RenderComponent({this.props.model.get('name')}
); } }); {% endhighlight %} However, this component on its own can't react to the model's field being changed. Instead, we can add a listener for the model's `change` event that tells the component to re-render: {% highlight js %} var DisplayView = React.createClass({ componentDidMount: function() { this.props.model.on('change', function() { this.forceUpdate(); }.bind(this)); }, render: function() { // ... } }); {% endhighlight %} Then, we add another component that will actually change the `name` field: {% highlight js %} var ToggleView = React.createClass({ handleClick: function() { this.props.model.set('name', 'React'); }, render: function() { return ( ); } }); {% endhighlight %} Finally, we create a model and render both components using JSX: {% highlight js %} var model = new ExampleModel(); React.renderComponent((