/ Web development

Why I like Angular more than I like React.JS

Last week Lieke Boon (@Lieke2208) on twitter asked what people liked best, Angular or React. Good question, which deserved an honest answer from my side.

It's a bit like asking someone for their favorite music or color. It's a very personal thing. You can expect some pretty heated responses on the subject, which I of course got very soon after I told Lieke that I like Angular.

He might be right, I am a person that is very accustomed to MVC. It's too bad that 140 characters guarantuees one thing:
Miscommunication. Wim probably doesn't want me to think that I am wrong for using MVC. Also I am pretty sure that
I didn't mean I haven't tried it and am just shouting messy, because it looks like that in hello world demo code.

The tweets call for a better explanation in more words. So here it goes on my weblog.

What is React.JS?

You may or may not know about React.JS, so let's explore that first. React.JS is a framework that offers a way to build
user interface components using Javascript. It offers functionality for building view related things only according to the website.

Which means, you don't get any help building controllers and models. You have to find another framework for that.
Or you could use plain javascript classes and jQuery to talk to the backend. Which is plenty for most things if you ask me.

In order to build a component in ReactJS you define a new class like in the sample below

var PeopleList = React.createClass({
    componentDidMount: function() {
      var self = this;

      myService.getPeople().then(function(data) {
        self.setState({
          people: data
        });
      });
    },
    render: function() {
        var people = [];

        for(var i = 0; i < this.state.people.length; i++) {
          people.push(<li>{this.state.people[i].name}</li>);
        }

        return (
          <ul>
            {people}
          </ul>
        );
    }
});

You can render this component on the page, by invoking the following code:

React.render(<PeopleList/>, document.findElementById("my-placeholder"));

This piece of code does the following. First it finds a placeholder element on the page.
After that React will instantiate the peoplelist component and insert it into the placeholder
DOM element.

Once instantiated the componentDidMount function is called which loads
the data. In the sample above, the data is loaded using a service class that I created myself.
It returns a promise. In the then function I will call setState to update the state of my component.

Set state updates the state of the component and automatically asks for a render. Which is
implemented using the render method. The render method is responsible for transforming data into DOM elements.

Properties on React.JS are set only once and cannot be updated after the component is rendered.
State however can be updated and is used to work with dynamic data.

React.JS unlike Angular doesn't support two-way bindings in the normal sense of the word.
It does however offer events, which bind to functions on the component in which you can call setState
to update the state of the component. This allows you to create two-way bindings yourself. But with
full control over those bindings.

Other than the features I just described there's not a whole lot more about React.JS.
Which makes it a pretty compact and easy to learn framework.

Nice and compact

I like the fact that the framework is very small in terms of features. It does one job very well.
Concentrating on the user interface is a good move which I think more frameworks should make.
Communicating with REST services is rather easy as it is with jQuery and doesn't need a lot more.
The user interface on the other hand is riddled with weird stuff in jQuery which gets easier when
you use something like React.JS

Another thing that works really well is the fact that data goes one way in the React.JS components.
As there are no data binding options you can only flow data from your server to the user interface.
Sure you can bind events and get data from a textbox and put it back in the state of the control.
But when you set the state of the control, it still flows from your code to the user interface and
you control where the data goes.

React.JS also doesn't require a lot of boilerplate code to get things up and running. You determine
where and when to start rendering controls, so you get to set up the bootstrapping process and
determine when to load data.

JSX: A working solution, but it needs more work

As you might have noticed in the sample at the start of this post, there's HTML code in the javascript.
When you build a React.JS component you get the best result when you start using a language called JSX.
The JSX language is a mix of regular javascript and HTML-like syntax. The render method requires you to
return a DOM element to render. You can build that DOM element, but it is way easier to do that by just
typing the HTML elements you want and run the JSX compiler to convert the thing into runnable javascript.

It looks like you are mixing HTML and Javascript when working with JSX. But once you compile it down
to javascript you will get syntax that looks like this:

var PeopleList = React.createClass({
    componentDidMount: function() {
      var self = this;

      myService.getPeople().then(function(data) {
        self.setState({
          people: data
        });
      });
    },
    render: function() {
        var people = [];

        for(var i = 0; i < this.state.people.length; i++) {
          people.push(React.createElement("li",null,this.state.people[i].name));
        }

        return react.createElement("ul",null,people);
    }
});

JSX is a good find when you think of the amount of work you need to do to build DOM elements by hand.
But there are a few things that I definitely don't like about this approach.

First there are no editors that support the syntax well. Most editors break or don't over any syntax highlighting
when you start working with JSX files. I use Atom a lot. It has a plugin for the JSX syntax, but so far I haven't
had a really good experience with the plugin. I know this will get better, but right now it's a mess :(

Another thing I don't really like about the JSX syntax is the fact that it is HTML-like. Some attributes are different
from what you expect them to be. You cannot type in class but have to use className instead. Copy any of your old
HTML code and you will find that it is frustrating to convert existing code to React. Same goes for things like the for
attribute which is htmlFor in JSX.

It feels like typing HTML with one hand tied to your back, lazely hanging so you
feel like you can reach, where in fact you can't reach the keyboard.

This all has to do with the fact that JSX translates into React.createElement calls, but I think they could
have done a better job at translating the various HTML attributes. There's no good reason why they made it
the way it is right now if you ask me.

JSX is good for solving the problem of having to manually manufacture DOM elements, but it does so in a weird
way.

Also, when you start to build bigger components things tend to get messy with JSX. Too much of the HTML goo
and you cannot read what you're doing. It's very easy to fall in this hole, so a warning is in order here.

Some tips for people who start to work with React.JS

When you start to build JSX components you have to think very hard about how you structure your components.
Try to split the user interface into components as small as possible. Then compose those components into
a working user interface.

This sounds easy, just throw together lots of small components. In reality it isn't that easy. You will
learn very quickly that it takes experience and skill to make the right trade-off between reusable components
and components that can only be used once in a very specific situation.

I think the documentation needs a little more explanation on how to do this, to help first-time component
builders do the right thing.

So why do I like Angular better?

After writing everything down I think it comes down to a 51% vs 49% desision.
Angular works with strict separation of markup and behavior. Which works really well, because it prevents
people from creating a big mess in a file that regularly contains complex logic to control the user interface.

On the other hand, having a compact framework for just one job is great. It gives me a lot more freedom
to build everything else in the way I need it to be without having to bend myself over backwards to get it
going, because a framework tells me it should work in a certain way.

I think you should try React.JS out and tell me what you think. Also I am curious about things like performance,
so if anyone out there has a rough idea about that, let me know!