Skip to content

React.js plays nicely with other tools and other thoughts

August 6, 2014

tl;dr: I’m not completely sure about React.js yet just because it’s such a different approach, but I really appreciate how easy it is to use it in conjunction with other client side tools.

My shop is looking very hard at moving to React.js for new development and I’m scrambling a bit to catch up as I’ve been mostly on the server side for years. Partially as a learning experience, I’ve been using React.js to rebuild the UI for our FubuMVC.Diagnostics package in FubuMVC 2.0 as a single page application. While my usage of React.js on the diagnostics is mostly about read only data displays, I did hit a case where I wanted a “typeahead” type search bar. While a google search will turn up a couple nascent projects to build typeahead type components purely with React.js, none looked to me to be nearly as mature and usable as the existing typeahead.js query plugin*.

Fortunately, it turns out to be very easy to use jquery plugins inside of React classes so I just used typeahead.js as is. For the StructureMap diagnostics, I wanted a search bar that allowed users to search for all the assemblies, namespaces, and types configured in the main application container with typeahead recommendations. Since I was going to want to reuse that search bar on a couple different little screens, I did things the idiomatic way React wants to be used anyway and created the small component shown below:

In the not unlikely chance that the code below is mangled and unreadable, you can find the source code in GitHub here.

var SearchBox = React.createClass({
	componentDidMount: function(){
		var element = this.getDOMNode();
		$(element).typeahead({
		  minLength: 5,
		  highlight: true
		},
		{
		  name: 'structuremap',
		  displayKey: 'value',
		  
		  // Just a little object that implements the necessary 
		  // signature to plug into typeahead.js
		  source: FubuDiagnostics.StructureMapSearch.findMatches,
		  templates: {
			empty: '<div class="empty-message">No matches found</div>',
			suggestion: _.template('<div><p><%= display%> - <small><%= type%></small></p><p><small><%= value%></small></p></div>')
		  }
		});
		
                // Behind the scenes, this is just delegating to Backbone's router
                // to 'navigate' the main pane of the page to a different view
		$(element).on('typeahead:selected', function(jquery, option){
			var url = 'structuremap/search-results/' + option.type + '/' + option.value;
			FubuDiagnostics.navigateTo(url);
		});
	},
	
	componentWillUnmount: function(){
		var element = this.getDOMNode();
		$(element).typeahead('destroy');
	},

	render: function(){
		return (
			<input type="search" name="search" ref="input" 
                          className="form-control typeahead structuremap-search" 
                          placeholder="Search the application container" />
		);
	}
});

 

There really isn’t that much to the code above, but the salient points are:

  • The componentDidMount() method fires just after React.js renders the component, giving me the chance to apply the typeahead jquery plugin to the DOM element.
  • In this case the component is a single HTML element, so I could just use the getDOMNode() method to get at the actual HTML DOM element. In more complicated components you can also use the refs collection.
  • I cleaned up and deactivated the typeahead plugin in the componentWillUnmount() method whenever React.js is tearing down the component to clean up after myself

To use the component above, I just embedded it into another component as more or less a custom tag in the jsx markup:

var Summary = React.createClass({
	render: function(){
		var items = [];
		
		this.props.assemblies.forEach(function(assem, i){		
			items.push(AssemblySummaryItem(assem));
			
			assem.namespaces.forEach(function(ns){
				items.push(NamespaceSummaryItem(ns));
			});
			
		});
		
		return (
			<div>
                        
                        // This is all you have to do to include it
			<SearchBox />
			
			<hr />
			
			<ul className="list-group">
				{items}
			</ul>
			
			</div>
		);
	}
});

 

So what do I think of React.js so far?

Um, well, React is interesting. I know that my initial reaction was similar to many others: “you seriously want me to embed HTML markup directly into JavaScript?” Once you get past that, it’s been very easy for straight forward usages of rendering JSON from the server into HTML displays. I won’t make any permanent judgement of React.js until I use it on something with much more complicated user interactions.

To speak to one of React.js’s major design philosophies, I’ve never liked two way model binding in any user interface technology I’ve ever used because I think it so easily obfuscates the behavior of screens and causes unexpected side effects. I’m not completely sure how well the one way data flow thing is going to work out in bigger applications, but I’m at least initially on board with the React.js team’s basic design philosophy.

One thing to consider is that React.js is much more of a library that you’d use as opposed to an all encompassing framework like Angular.js or Ember.js that you have to wrap your application around. The downside of that is that React.js doesn’t really do anything to encourage separation of concerns or help you structure your application beyond the view layer, but the old presentation patterns that came out of older technologies still apply and are still useful if you just treat React.js as the view technology. You’re just on your own to do your own thinking. The upside of React.js being just a library is how easy it is to use it in conjunction with other tools like the entire jquery ecosystem or bits of Backbone.js or even as something within frameworks like Angular or Ember.

I’ve also done a little bit of a proof of concept of using React.js as the view layer in a possible rewrite of the Storyteller UI into a pure web application. That work will probably generate much more interesting blog posts later as it’s going to require much deeper hierarchies of components, a lot more complicated user interaction, and will push us into exploring React.js usage with separated presentation patterns and much more unit testing.

At least in the circles I run in, there’s been a bit of a meme the past couple years that Functional Programming is the one true path to software programming and a corresponding parallel backlash against almost everything to do with OOP. If React.js becomes more popular, I think that it might help start a rediscovery of the better ways to do OOP. Namely a focus on thinking about responsibilities, roles, collaboration patterns, and object composition as a way to structure complicated React.js components instead of the stupid “Class-centric,” inheritance laden, data-centric approach to OOP that’s been so easy for the FP guys to caricature.

 

* I’m not really working much on the client side, so what do I really know? All the same, I think the backlash against jquery feels like a bit of throwing the baby out with the bathwater. Especially if you’re constraining the DOM manipulation to the purely view layer of your code.

About these ads

From → Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 28 other followers

%d bloggers like this: