React Impressions

Let me start with a mandatory statement that many first-use-React-blogs start with: “I have played a bit with React and its great. And…”

Having recently completed a decent sized project in ReactJS, I have to say, once in a while there comes a library or framework that truly makes you go back to the basics and think. Despite much gained knowledge, it is fascinating to see that human brain collectively misses the fundamentals as “progress” happens. Much like an experienced cricketer suddenly losing ‘form’ and is adviced to go back to basics. It is not that he forgot to how hold his bat, but that intuitive coordination or that ‘elegant touch’ has disappeared. Perhaps we humans are not wired to over-learn! From simple to complicated to simple, we keep oscillating, just like we keep regurgitating the centralized and distributed system concepts.

It also emphasizes two underestimated facts in software engineering:

1. Creating good software is hard
2. Keeping it simple is even harder

I still remember Rod Johnson’s impacting book ‘Java without EJB’, (I was advocating the same in one of my early projects – removing all EJBs because its complexity did not make sense and the book gave me a lot of cannon). Spring framework made a great impact on many web developers then, bringing in IoC principles into a Java container. (Spring wasnt the first one though, PicoContainer was).

Facebook’s ReactJS is one such framework going back to basics. Apart from the usually quoted strong features like VirtualDom, simple lifecycle model and one-way data flow, what is it that really made React tick? After all component based frameworks are not new – Awt/Swing, Tapestry, Vaadin, GWT, JSF/Seam, Wicket (all Java based) and several Javascript-based were successful – but they all fell into the trap of hiding the complexity of Javascript (and to some extent HTML/CSS) from the developer and that turned out to be a costly decision. Everytime Javascript and HTML standards evolve or browsers support something new, these frameworks have to undergo quite a bit of refactoring. Remember, both designers and front-end developers ultimately like to nano-control the HTML output.

Among the existing component frameworks, the gap between the ‘framework’ and Javascript/HTML is shortest in React. Compared to many frameworks that advocate a structure like .html,.js and .css for each component, React neatly rolls them all into one testable unit, surrounding it with a simple lifecycle. And with the virtual-dom concept, you can apply same concepts to mobile or even desktop apps.

Some complain that JSX is ugly. I first thought same, (I am not a big fan of XML based structures), but it took me all of 10 minutes to overcome it. In fact, I think its one of the smarter things that has come out of React: making Javascript expressions look like HTML. It is quicker to learn JSX than yet another templating language. Passing properties and reading state just feels syntactically familiar.

Another common complaint about JSX is that it makes if conditions and for-each syntactically harder, compared to say AngularJS ng:if/ng:repeat or Handlebar-type syntaxes.

AngularJS:
<span ng-if={showElement}>I am here!</span>;

JSX:

return (
showElement ? <span>I am here!</span> : undefined;
)

While the JSX version does not look concise, the ‘if’ and ‘for/map’ are natural and readable in programmatic syntax than in declarative syntax. Not only that, it can be elevated to a function to make the component reusable. And then it also provides an incentive to make the function stateless – so the component is now slowly turning into a dumb component. AngularJS, though concise, feels more XML-ly than React and you cannot reuse the <span> element as-is in some other place or context (unless you elevate it to a directive). The JSX downside appears to be that you keep creating component wrappers, but isn’t that problem to solve – making composability easier?

The biggest advantage of such componentization is, it also makes unit testing much more delightful. In our project, we use Mocha+Chai+Sinon, which seem to work pretty well. In React, you start to think in terms of composability, than just a page. Many a time, we wrote a complex component, but quickly dissolved/abstracted it into dumb components, by breaking out its props and state.

That’s another thing about React – the learning curve and refactoring is comparitively less steep than others, with only a few concepts to learn.

I am also often asked how long will this framework last? Will Polymers and Web Components take over the browsers? Unfortunately, the Delorean only went upto 2015 and the Almanac probably did not mention React.

Defining React Routers via API

One of the issues I faced while using React for my project is which Router to use? React obviously being a new framework on the block, there are plenty of plugins/components that are being actively developed and not many are (yet) stable. Some plugins are just enough different for you to want a new feature, but it wont support other features required. You can see how bullet-point engineering does not help much. You gotta try out a few and see what works best.

For the Router, react-router is the most popular, featured and well-documented, but it (v0.12.0) did not have one feature I was looking for: Ability to define routers closest to the handler itself.

All the routes go into a single file, usually your app.js, like this:

var routes = (
  <Route name="app" path="/" handler={App}>
    <Route name="login" path="/login" handler={Login}/>
    <Route name="logout" path="/logout" handler={Logout}/>
    <Route name="page1" path="/page1" handler={Page1}/>
    <Route name="page2" path="/page2" handler={Page2}/>
    <DefaultRoute handler={Login}/>
  </Route>
);

Router.run(routes, function(Handler) {
  React.render(<Handler/>, document.body);
});

If the application grows, this is less than ideal and can bloat the app.js. And it somewhat breaks modularity too (even though the app.js will eventually know everything, it forces you to wire the routes statically). The react-mini-router defines the routes as part of component as a mixin and I think thats pretty convenient.

With react-router v0.12.2+ the routes can be configured via api. This is not documented yet officially, afaik.

approute.js

module.exports = Router.createRoute({ name: "app", path: "/", handler: App});

auth.js

var AppRoute = require('./approute.js');
Router.createRoute({ name: "login", path: "/login", parentRoute: AppRoute, handler: Login});
Router.createRoute({ name: "logout", path: "/logout", parentRoute: AppRoute, handler: Logout});

page1.js

var AppRoute = require('./approute.js');
Router.createRoute({ name: "page1", path: "/page1", parentRoute: AppRoute, handler: Page1});


app.js

var AppRoute = require('./approute.js');
Router.createDefaultRoute({parentRoute: AppRoute, handler: Login});

Router.run([ AppRoute ], function (Handler) {
  React.render(<Handler/>, document.body);
});

Notice how the variable routes is replaced with [ AppRoute ]. This is important!.

In auth.js, if defining multiple routes, If you dont want to use parentRoute property, you can also do this:

AppRoute.addRoutes([ LoginRoute, LogoutRoute ]);