A Brief Introduction to ReactJS

On Strengths and Weaknesses of ReactJS

Posted by Heikki Kupiainen/Oppikone on 21.11.2016 07:12:40

Why ReactJS?

If you think you are good at JavaScript programming chances are that you still won't get a project unless you are familiar with ReactJS. That is because ReactJS is momentarily in the center of a hype-storm and will remain there until the next framework pops up that will get the hyper crown. Remember, the previous hyper king was AngularJS and before that there were many others like Backbone, JavaScriptMVC, EmberJS etc. It is typical for inexperienced programmers to emphasize importance of frameworks over design patterns. One good example of this kind of framework over-glorification is the much-hyped "dependency injection support" in AngularJS that I even wrote another blog post about - but that's another story.

How About Networking?

Interestingly, there is a common misconception that ReactJS kind of "solves" the UI. But a serious browser based single page app (SPA), for instance, inevitably needs networking functionality (AJAX). Yet ReactJS' "networking" functionality is a very primitive fetch wrapper function. That does not compare well with jQuery's advanced AJAX options. It is okay to use ReactJS for rendering views but really, you'll be better off using jQuery for networking. And once you include jQuery into your project, why not to use also jQuery's superior DOM manipulation methods? But of course, that would be in conflict with ReactJS's sweet "virtual DOM" idea, right?

When you are looking for someone to create a web app, requiring ReactJS skills without even mentioning jQuery is a bit like ordering a car without an engine. But of course, things don't need to be that black and white. There is nothing that can prevent you from loading the data with jQuery and then initializing ReactJS elements with that data. I'll show later how!

If what you actually want to do is rendering views on server side using ReactJS then you are just reinventing the wheel and doing exactly the same thing what they always did with PHP, JSP, ASP, RoR, Django etc. Then you are just using ReactJS as a yet another server side templating engine - even if this time JavaScript based and decorated with new buzzwords - but conceptually really just continuing a tradition from the last millenium. It is okay to do so and it's great for creating static content but then just don't call it SPA because the point of an SPA is that the browser client renders the views and not the server. And that requires networking with AJAX because the client needs to load templates and data dynamically from the server. Ideally a true SPA only loads data and templates - not readily rendered views.


It's always useful to get started with new frameworks by checking out some complete examples that already have a readily made project structure. For ReactJS, there are many tutorial repos available for instance Koans ReactJS github repo. But of course, you can also install a very basic example project directly from Facebook's repository.

In my last blog post I introduced some (who knows?) controversial OOP hacks using car-related examples to demonstrate inheritance. Therefore, we'll remain in the car manufacturing business in this blog post as well, creating a web frontend for our car models.

It's time to put some Car concepts into production and create a Car App with ReactJS! For this reason, the sample project will have name my-car-app. As a prequisite, first install ReactJS toolkit:

npm install -g create-react-app

But please note that if you use Ubuntu Linux and want to install NodeJS via apt-get you will encounter a problem when trying to use ReactJS-related npm tools that depend on NodeJS. When you execute:

create-react-app my-car-app

There are changes that you'll get an error:

/usr/bin/env: node: No such file or directory

No need to panic! The problem occurs only because in Ubuntu, NodeJS is named as "nodejs" while npm expects "node". There are two two ways to solve this problem. You can stick to your OS package manager's default Node installation or you can download a brand new version directly from provider's web site.

Method 1: Install Node And NPM via Package Manager

I warn: this is the hard way. But if you still prefer using the package manager you just need to create a symbolic link that fixes the problem:

sudo ln -s /usr/bin/nodejs /usr/bin/node

Beware that your default NodeJS version might be deprecated. If that is the case you'll get a warning when using npm to install ReactJS related tools - and even worse: they won't work!

Just download the newest NodeJS version from NodeJS web site and extract it to wherever you like. Remember to update the symlink accordingly. I have:

sudo ln -s /home/heikki/tools/node-v6.9.1-linux-x64/bin/node /usr/bin/node

If this doesn't fix it it's probably because you are using operating system's default npm installation which might be deprecated. Uninstall npm and create a symlink to npm installation as well:

sudo ln -s /home/heikki/tools/node-v6.9.1-linux-x64/bin/npm /usr/bin/npm

Method 2: Install Node And NPM Directly From Website

I strongly recommend installing Node and NPM directly from the provider's website. If you use the package manager it is granted that you'll get an outdated version. Moreover, you must struggle with the above mentioned issues. Just downloaded the package and extract it to your favorite location. And remember add the binaries to your path by editing .bashrc file. I added a line as follows:

export PATH="$PATH:$HOME/tools/node-v6.9.4-linux-x64/bin"

If your OS does not support Bash then I recommend installing a better one!

Creating Your First ReactJS App

Then create the project directory (if you didn't do so yet) and start the development server:

create-react-app my-car-app
cd my-car-app
npm start

If everything went right you should have a skeleton for your first ReactJS app by now. The main application file has been generated as ./src/App.js. You can just start tweaking it to create an app you always wanted to have.

When you want to publish the production version of your App make sure that you have a pushstate server installed:

npm install -g pushstate-server

It's particularly nice to have pushstate-server working because it helps you try out your build before publishing it. So, finally build your app:

npm run build

That's how it works. The result is also available here. I also created a GitHub repository for the code samples I wrote for this demo. Feel free to check it out.

Now, let's take a look at ReactJS's ideology. ReactJS is a framework really focused in manipulating DOM, introducing a concept of "Virtual DOM". You can declare your own elements and use them just as if they were any normal DOM elements.

And syntax for using CustomAppHeader would look like this:

Creating Complex Components

Next, I'll show how to create more complex components. When you render any virtual DOM component you can embed your custom components into the output html of each component. That will, by definition, lead to more complex composite components. But before that, let's create a hard-coded dummy component to render a html list element containing some cars:

Now, we are ready to add the CarList component to the main view and have our cars listed on the web page:

Looks nice? Hold on! The truth is that we created some code that is not browser-supported JavaScript. ReactJS compiles this code into a machine-generated "bundle.js" file that isn't a particularly encouraging target for debugging. You don't need all this to write object oriented JavaScript code. Have a look at my article on OOP in JavaScript for retrospection. But don't let me discourage you! Let's proceed and create a more advanced car list component that takes an array of car models as input parameter and renders it as an html list:

If you think that the code above turns a categorically drop-dead simple concept such as rendering a list in a template into an overly complicated and counter-intuitive hogwash, then take a look at some conventional template engine such as MustacheJS or EJS. Now, let's embed ParameterCarList into the main app:

Note that the ParameterCarList component here takes the value for cars parameter from getCarList function. We'll implement that function in our main App class:

Needless to say, a ul/li list in html without any formatting will look so ugly that I don't even dare to add a link to the outcome of the code I described above before I add some responsive formatting. And what is the best solution to format html? Bootstrap of course! With Bootstrap you can add reasonable and responsive layouts to your App no matter whether you created it with ReactJS or anything else. Our car list formatted with Bootstrap will look like this:

The example is also available here.

Filtering Lists

If we want to stay in car business we must be able to offer many different car models. And when we add more cars to the list then users must be able to filter the list somewhat to find exactly those cars they are looking for. Let's implement a CarFilterList that includes a search field, list filtering logic and the actual list element, all formatted nicely with Bootstrap:

Note that I have embedded a BootstrapList component inside my CarFilterList. That's because I want CarFilterList to contain the logic for filtering cars and BootstrapList a somewhat more general component that just renders any list it gets as a parameter:

The result is going to look like this:

The example is also available here.

The ES6 Way

When coding with ReactJS using ES6 like I did in these examples there is a nasty trade-off we have to deal with. Our code is being compiled into a bundle.js file that is almost impossible to debug. So good bye breakpoints! Well of course we can add some alerts and console log messages. So welcome back to the 90's! When you write ReactJS code you must also get used to the idea that you often see just a white screen and the only way to know what went wrong is to undo your additions word by word until you see that it works again. In my opinion, if you can't properly debug an app, it is a disaster. The ReactJS community is too ambitious forcing developers to use ES6 ahead of time. ES6 will be a part of future but a Babel-based solution, at least at the time of writing this, is just too bad because it sacrifices debuggability. But there is a reason to expect improvement to this issue anytime soon when ES6 support becomes more available in browser implementations.

Model Bindings

ReactJS model binding provides a certain advantage in updating the model layer from user inputs. It is a nice practical shortcut that you can add a model binding to a UI element that will automatically update the model when user edits a text area, text input field or selects a checkbox. This works OK for very simple core components. Yet it is not that much more difficult to just add a classic event listener "onchange" and write an updater method. Basic model binding will fall short when you try to add a just little bit more advanced UI widget. And it will fall short when you want to add some custom validation. And you will be needing custom validations. At the end of the day, you will be writing custom updater methods anyway.

Putting It Into Context

There are some parties that erratically praise ReactJS as some kind of a silver bullet in UI development. However, ReactJS covers really only the View aspect of MVC (Model-View-Controller) trinity. Any software, whether running in a browser or somewhere else, consists of many aspects and rendering views is just a tip of the ice berg.

To build good software, ReactJS is not all what you need. You can use ReactJS to render views but you don't need ReactJS really to do it. There are many alternatives for rendering views. Also ReactJS's virtual DOM operations are rather cumbersome compared with jQuery's power and flexibility. ReactJS tries to solve this issue by using JSX templates. However, JSX has a downside that it must be embedded in either ES5 (JavaScript) or ES6 code that is then compiled into a bundle that the browser (not human) can understand. But if you really want to separate templates from JavaScript code like many do, you'll be better off when you use some templating engine such as EmbeddedJS (EJS) or MustacheJS. Those templates can be loaded dynamically from server on demand using Ajax. When creating a true SPA with serious networking capability, jQuery is what you need for networking. And once you use jQuery, why not to take advantage of all power it has?