comedy-shakespeare

Encapsulating JavaScript

There’s an awesome article on the Internet, React.js Introduction For People Who Know Just Enough jQuery To Get By. After reading it, you may really see the power of React. If you are writing your websites with jQuery, you might consider either Angular, Ember, Backbone or one of the other more or less known front-end frameworks. This will make your development easier. But let’s take a look at React.

With React you can easily split your project into small independent pieces, called components. Say, for example, you have a complex webpage. You might then have a layout, styled so as to support different themes, so it does not depend strictly on partials’ positioning and styling. And a bunch of partials, being rendered within that layout. Then you might split each of all those partials into reusable components, so you can compose your pages by simply placing each component on its place.

React is a library with a special language, called JSX, which allows you to define components of your pages in a manner, where both view (HTML code) of your component and logic (JS code, handling the component behaviour) are defined in one place:

Although building components with React may seem like polluting your code with HTML, it is a really great idea to keep your HTML code near to the JS code handling it. But React (JSX, actually) has its own restrictions for component definition. For example, you cannot use two tags next to each other inside your component – it is a requirement to use exactly one top-level tag. And all the variables, needed to be bound on front-end (so you may either display its value or set it from user controls) are stored in the this.state variable of your component via getter- and setter-methods (but I will tell you how to overcome that particular restriction later):

Moreover, as you might noticed from the two examples above, placing a component on a page is done with JavaScript (and I will show how to overcome this restriction too).

So let’s try it out and create our first React component!

The Architecture

This article relies on JavaScript, so let’s be kind and create the initial project structure for a typical JS project. Just like this:

Project structure

It’s always great to have a typical structure for a project so anyone new to the project will not get lost.

We can assume that we will always have a set of JavaScripts and stylesheets, used on the front-end. We also may need some third-party libraries, managed by NPM or Bower. And it is always (by which I mean not for JavaScript projects only) a great idea to have your changes being tracked by some version control system. I like Git the most.

Based on those few assumptions, we will need a folder with javascripts and stylesheets sub-dirs, as well as .gitignore, package.json and bower.json files (select the ones you need).

You can initialise the whole NPM project with npm init. This will display an interactive menu, where you can specify your project details like description, version, link, some basic dependencies (like amd, require.js, etc., but we do not need any of those) and others. And this command will fill out the initial version of package.json file, so you may fill it out as  you wish, adding dependencies, scripts and friends. Here’s how it may look like:

Adding Bower to our project is very similar: bower init. This command is almost the same as npm init – it also creates a sample bower.json file. We will use it to specify React.js dependency. Below is the sample bower.json file:

In some cases, as with this article, we may need to compile some resources. For that purpose we may create something like a  build directory, where the compiled JS and CSS files will be placed. And define the build command in the package.json file, within the scripts section, so we may build our project running npm build or something very similar.

A very simple introduction

Preparing a layout template

Let’s create a layout for our sample webpage. Currently it will be just a blank HTML page, with nothing inside (even no CSS/JS includes!):

But if you don’t want to type all those tags manually, there’s a great solution for you: Emmet. With Emmet you may just type html:5 and press Tab in your favourite text editor (I feel comfortable with both Sublime and Atom, but you can run Emacs or Vim and still use Emmet) and all the code will be generated auto-magically!

Front-end dependencies

Now, let’s add bootstrap and react scripts to our project. The best way of doing this is using Bower. There are two ways of adding dependencies with Bower: manually editing bower.json file or using the command-line.

If you decided to manually edit the bower.json file, remember to set precise versions for each dependency. Otherwise, you may face the situation when someone installs your project and uses newer versions of the libraries, which are incompatible with the code that uses them (for example, some functionality disappeared or argument list for some function was changed).

Here are the lines you will need to add to your bower.json file to proceed (versions are the newest, as for the time of writing this post):

If you have chosen the CLI way, consider this command:

I preferred the CLI way as it chooses the correct library versions automatically and is really faster operation.

Now when you finished initialising your project, you can add React’s JavaScript and Bootstrap’s CSS to the layout. As long as you track front-end libraries with Bower, you need to reference them from bower_components directory:

First NPM task

You may want to define a task in your package.json file to make installation of the Bower dependencies simpler:

This may be useful later, when building and deploying a project. Here I used the local version of Bower in the script, so as not to make another project requirement of Bower being installed globally. The same approach is used in this article for the building task. Global dependencies are not a great solution, because they require other developers, who install your project, to install tools globally, what possibly can break  the tools installed on their machines already.

JSX vs JavaScript

React uses JSX. JSX has two meanings. According to the List of languages that compile to JS, JSX is an extension of JavaScript with human-friendly OOP and type safety support. In the universe of React, JSX is an extension of JavaScript too. But in this case, JSX only allows us to create DOM elements from within the code in a DSL-style.

To explain what DSL-style means, I will show you two examples:

the non-DSL way:

the DSL way:

Both JSX branches are, again, extensions to JavaScript, so they need to be compiled to ES5 (also known as “normal JavaScript”) to make the code understood by the browser. For this purpose we need a compiler. For React this is called react-tools. So let’s add it as a dependency inside our project’s  package.json file. This will add the jsx utility to the node_modules sub-dir. We can define another build task within the package.json file:

This task compiles all the scripts from the src/javascripts/ directory and stores the compiled javascripts in the build/ directory.

First component

All the components are made by simply calling the React.createClass() method and providing it with the component’s rendering method (a method that returns the component’s HTML), its initial state (something like Angular’s $scope) and some event handlers. Just check it out:

Here you can see a few restrictions, created by React:

  1. you need exactly one top-level tag for your component
  2. you may not use the class attribute within elements, use className instead

And this is how this component is used:

Note: you may not use the <TweetBox /> tag from within the HTML.

Now let’s write that component in the javascripts/app.js file and reference it in the layout, at the end of <body> tag; to make it load when the whole document is done loading:

To see the page we’ve written in action, first compile the sources with npm run build to compile the JSX code to JavaScript and use it in the layout template.

State

The component’s internals are stored in the state variable. This is something like Angular’s $scope. React adds a method to initialise your component’s state, called getInitialState(). It should return an object which represents the initial state. State variables may be accessed via this.state.myVar and interpolated in the template with curly-braces: {this.state.myVar}. So you can do something like this:

State may be changed with the setState() method, receiving… an object! But this time, the object for setState() represents a set of new field values. So, for example, using the syntax:

will not replace the whole state with the text field only. Instead, it will modify the text field only and leave maxLength unchanged.

But when can we call changeState()? In Angular this is done with data binding. But in React we have events. Yes-yes, simple DOM events!

So, for example, we can set the onChange event in the <textarea rows="10" cols="50"> and just handle it:

Yeah, it’s not as pretty as Angular…

React: conclusion

I assume React’s way of doing websites is nice until you learn something better; at least, switching from jQuery you can make your webpage’s code look much better with React! But still, writing HTML in JavaScript code?..

shakespeare-3

Alternatives

Riot

But wait: there are alternatives! Riot continues the React experience of state. But it achieves this with much prettier code. But the main advantage of Riot is ES6. Yeah, when both libraries use compilation, why reject the future and re-invent the wheel? In this way Riot makes your code much clearer. Check this out:

Everything looks great with Riot: its size is much lower than React’s; it has ES6 and nice syntax; it does not turn your JS code into a substance on the edge of two worlds – the view layer and the logic layer; it even has scoped CSS!..

But Riot has one huge drawback: XHTTPRequest. By default, you can define your components inline, just within your layout page. But as long as it is a mix of HTML and JS, the browser will not correctly respond to your page, throwing strange exceptions . So, you may decide to extract your components into separate files. But here you might face the fact that most modern browsers do not allow asynchronous requests to  files without the protocol being provided (so you can not load project files via AJAX while testing the project locally). And that’s how Riot loads your components – via AJAX. So you either need to pre-compile your components or run your project on a web server.

Angular 2.0

Great news for each and every AngularJS fan: the essence of future of web development, Angular.js 2.0 is coming! It is built with TypeScript, which is even more powerful than ES6! It provides developers with a component architecture – HTML and JS encapsulation, but in an even more sophisticated form!

So, for example, our <tweet-box> component in Angular 2.0 might look like this:

tweet-box.ts:

tweet-box.html:

Here, as you can see, data binding is being used, so there is no more need for event handling. And you can use all the power of TypeScript.

But it is only the endpoint, which you must reach first. To use all that power, you will need to use NPM and install a few dependencies:

Now we need to create our component. Angular2 provides two ways of writing code: Dart way and TypeScript way. Dart is a great language by Google, which compiles into JS. On the other hand, TypeScript is another great language, but made by Microsoft. Either way you choose is nice, but from my point of view, Dart is

  • slower at compilation
  • less documented (for Angular2)

Thus, let’s use the better documented and faster TypeScript. Writing in TypeScript slighty differs from JavaScript, although the in the end it will be same EcmaScript 5. Let’s create our first Angular2 component:

You might’ve noticed the annotation, import statement, the FORM_DIRECTIVES constant, the templateUrl property and ES6-style class we used. Yes, these are features, provided by TypeScript. The @Component directive tells Angular to define our component. selector attribute defines the name of our new HTML5 tag, which will be used for our component. directives attribute is a draft drawback (in my opinion), telling which directives will be used by template. And the templateUrl attribute tells Angular, where to find the template for our component.

Now, the template. It is not that simple as for Angular 1.x. We need to use a <textarea> tag in our template to capture user input. Here Angular2 proposes two options: the temporary variable, defined as our textarea’s attribute #var_name and the NgModel directive. Temporary variable is not what we are looking for, because it binds our variable to a HTML element itself. So in order to get its value, we will need to use either .value or .innerHtml property. And that is not that accurate, as with NgModel. And that’s why we were made to add directives parameter to the @Component annotation, to permit all the form directives being used in our template.

The template itself looks… interesting… We are barely using attributes, allowed by HTML5 standard, like with Angular 1.x:

But we can live with it, can’t we?

The last thing we need to do to make our Angular2 example run is build process. I’ts a bit complicated, compared to other libraries in this article, but it is caused by all the cool features of TypeScript we used. With great power comes great responsibility! That’s why we need the systemjs library – it takes TypeScript files, compiles them to JavaScript and places them in the right place. We then tell systemjs to load our module (in my case I called it app). And we are ready to use our component, defined in that module:

So now our sample is complete and you may run it. Remember, we installed one more dependency, we did not talk about? Yes, the live-server! This is a great tool for developers – it allows one to run server once and just write the code. When the code changes, server detects that change and automatically reloads the sources and refreshes the browser. Cool, huh? To use this nice tool, you only need to navigate to the directory the index.html file lays and run live-server command (in case of global installation – the -g option for npm install; if you did not specify this – you may run the live-server with ./node_modules/live-server/live-server.js). Yes! That easy!

Fin

Looking at these three libraries, I can say that it is definitely Riot which made my day. It is as simple as it is powerful and small. It lacks two-way data binding, but makes much more sense than React. And yet it does not require you to go mad installing all those dependencies to make it work. Moreover, if you combine Riot with WebComponents (or Polymer), you may end up building totally standalone, reusable web page components. And then making a new website will look like constructing a toy with Lego.

All the examples mentioned in the article can be found on my GitHub account: