ReactJS Gotchas #001

Tags: Mocha, Chai, Sinon, React 0.13.3

Problem Context: Run a unit test using Mocha against a Form.

Error: Invariant Violation: addComponentAsRefTo(…): Only a ReactOwner can have refs. This usually means that you’re trying to add a ref to a component that doesn’t have an owner (that is, was not created inside of another component’s `render` method). Try rendering this component inside of a new top-level component which will hold the ref.

Example:

beforeEach(function () {
rendered = TestUtils.renderIntoDocument(
<MyComponent ref="myComponentRef" param="10" />
);
});

Solution

Don’t use ref attribute for the component when running a unit test (ie remove ref=”myComponentRef”)

Advertisements

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.

His Last Framework

Its been a while since I visited my pyschiatrist and now, Chiropractor Dr. Pear – Perspective Readjustment Specialist. Last time, he helped me cope up an aggressive experience with pair programming. The front-desk handed me a big chunk of forms to fill up my software history.

Years of experiencing web frameworks: About 18.
First framework of pain: JSP Model 2, perhaps Applet, can’t remember.
Latest framework of pain: AngularJS
History of major pain points: EJB, WebSphere, WebLogic, Spring, Fusion Middleware, Wicket, ASP.Net Web/MVC, SharePoint, Grails, SpringBoot, Backbone, Ember, AngularJS and innumerable minor ones.
What type of pain is this? (Select one: Sharp, Shooting, Numb): All of them
Approximate location of pain: Initially Back-end. Then moved to Front-end.
Exact location of pain: Depends on Mood.
Frequency of occurrence of major pain: About every 18 months.

I physically submitted the forms and started checking my tweet feed. New tweets from dzone on Top 20 Javascript frameworks; AngularJS Jobs; Best 35 CSS Frameworks; Top 15 build tools for Javascript; AngularJS vs.., no wonder I needed a therapy.

The nurse called me in and after the initial handshake of pulses and vital stats, she said 200. I was idly looking at the magazines – PlayWeb, Maximum Frameworks… Dr. Pear entered after a knock.

Dr. Pear (browsing thru my history rather than looking at me): Oh, Hello! Its been a while from your last visit.
Me: Yes, Doctor.
Dr. Pear: And what brings you here?
Me: Well, Ive been spinning my head with the next web application framework and I haven’t been able to decide quite…
Dr. Pear: Well, the short answer is “As a consultant you should learn all of them !”, ha ha ha… (after a pause) Yeah, yeah I know. Its the viral season of frameworks. The Javascriptarix flu shot we gave last month was really a placebo. So what kind of framework you are really looking for?
Me: (a bit hesitantly) Not sure, Ive been taking the Javascript MVC Kool-aid for the last couple of years, but it looks like the pain isn’t gone…
Dr. Pear looked at me a bit condescendingly and said “MVC eh? in Javascript? Didn’t you get high enough on it in the Java/.Net world?”.
Me: Well, the Java web frameworks are kinda relegated to providing data services these days…

I had not finished. It must have triggered a raw nerve in him and he went on to a mini lecture of sorts.

“You see, web frameworks come in two general flavors – MVC and Component. Java failingly flirted with the Applet component model initially, and then took a stab at MVC via JSP Model 2, while ASP.Net took the component route after its success with Visual Basic. Interestingly, Java increasingly adapted the component framework model, but Microsoft abandoned ASP.Net Web in favor of ASP.Net MVC. Java/JVM probably tasted all kinds of frameworks in many levels – MVC (Struts, Stripes, Spring, Grails, Play) and Component oriented (Seam, Tapestry, JSF & Co, Wicket, GWT). The fundamental problem with MVC is – it sprays your logic and model everywhere. Many developers struggle to organize it between “what-they-are” vs “what-they-do”. As the complexity increases, the code gets re-organized by features, each of which in turn have the m-v-and-c. Add on top of that, the domain models and view-models are usually different, the whole thing about models start looking like a beauty pageant.”

He paused a second, probably aiming for me to get the pun.

“Component frameworks couple model and view tightly, because a view makes no sense without a model. But the biggest problem for them came from somewhere else: Javascript. Many pure java web frameworks are relatively stable, because of a stable and backward-compatible Servlet API. But component frameworks relied too much on encapsulating Javascript and HTML and in JS world, Friday’s release is outdated by next day Matinee show. Ajax, jQuery and related libraries innovated way too fast and library encapsulation really made no sense. When the JS libraries went unsupported, it dragged the Java frameworks along. With NodeJs, NPM-modules and unit-testing frameworks offering a vastly superior build ecosystem, life became miserable for frontend developers, bogged down by verbosity and slowness of JVM build tools.”

Me: Well, that’s exactly why I am here for. What is the JS framework you would really recommend?
Dr. Pear: Of course Backbone. I love backbones, especially if they aren’t straight. Get it? Ha ha !

He realized I didn’t look at him very admiringly. He continued.

Dr. Pear: Ok. Well, I hate to say it depends, because you didn’t pay me to hear that. So let me tell you something else. With JS frameworks like Backbone, Knockout and Ember becoming first class citizens, server-side slowly mellowed down to doing CRUDGE-work (Create, Read, Update, Delete, Gather and throw Exceptions), now gloriously termed as Microservices Architecture. With AngularJS offering a complete MVC stack, it doesn’t make sense to write Views in server-side anymore.”

Me: So should I still stick with AngularJS MVW ? Besides its barrage of new vocabulary redefinitions like service, factory, provider, scope, directive, the next version 2.0 promises to be completely different and backward incompatible…
Dr. Pear: Yeah, I heard that. It appears that you really need to work on your persuasion skills on convincing your team about writing in new framework every year.
Me: (I looked at him awkwardly, wondering what to say)
Dr. Pear: (Ignoring my awkward pause) Well, the web has to evolve. Why do you think Javascript is going bonkers with frameworks – they have to compete with rapidly advancing browser features, handheld and wearable devices. Who knows, Javascript could be running inside your brain tomorrow. Ok, so you are now tired of MVC in Javascript world also. What about Facebook ReactJS?
Me: ReactJS. Yes I’ve heard of it. Isn’t that a component oriented JS framework?
Dr. Pear: It sure is. You write HTML directly within Javascript or CoffeeScript or Typescript in an XML like syntax and compile them to Javascript.
Me: Im not sure I like the sound of that. Thats not even the best practice.
Dr. Pear: Well, its time to Refactor the Best Practices too. IMO, ReactJS may indeed work out well, because unlike the Java component frameworks, its closer to Javascript, it uses Virtual DOM providing fantastic rendering speeds and helps write isomorphic apps. If you get used to JSX, you will love it.
Me: What about Services?
Dr. Pear: Use one of the many flavors of Flux, Reflux, Fluxxor, Alt – the Action oriented one-way-data-flow-store.
Me: Hmm, that eerily reminds me of Struts. So, there is no really a best framework?
Dr. Pear: There is one – come up with your own. You will surely get a few fans.
Me: What if I get bored and jump ship to another framework? What about the developers who depend on my framework?

“Send them to me!” Dr. Pear said calmly, washing his hands for no reason. “If anyone thinks JS frameworks have more than 18 months of fame, they need a Perspective Readjustment”.

As I was leaving, he gave a parting shot, “Just remember one thing, if it makes you feel any better: no matter which framework, you are solving only a single problem: Delivering html to a browser. And by the way, if you haven’t selected your styling framework, I am open on Saturday afternoon”.

“Er.. Thanks, I will think about it”, I said as I flipped my phone to follow @ReactJS feed on my twitter.

As I was walking out I could see him frantically typing on the screen “Successfully readjusted for component framework. Will likely come here in the next 12 months looking for Web Component and Polymer adjustment.”

Note: Title is a tribute to AC Doyle’s His Last Bow.

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 ]);