Don’t blame the framework: my experience with AngularJS and ReactJS
In the past few years, websites have evolved into complex web applications, and what once was land of simple business informative pages, now is home to Facebook, Slack, Spotify and Netflix, changing the way you communicate, listen to music or watch movies. Front-end development has reached a new level and now requires more attention than it used to.
Just as for many front-end developers, our stack used to consist of HTML and jQuery. We would do AJAX requests to our backend, render the new chunk of UI on JavaScript and insert it into the DOM. User actions were tracked by binding events and callbacks to each of the elements. And don’t take me wrong: this is just fine for most applications.
However, when an application grows considerably, a couple of issues start being more frequent than expected: you forget to update all places where a value is displayed in the UI, no events are bound to the content added by AJAX, just to name some — this list can be very long. These are signs that your code is not maintainable, especially when developing together with a team. Using a front-end framework provides a formal way to write collaborative code that you can read, write and update.
1. The Dawn of React
When our team first felt the necessity of applying a front-end framework, we put some options on the table and it came down to – guess what? – Angular and React.
Angular was by far the most mature candidate: it had a big community and you could find third-party modules for most of the common use cases.
React was giving the first big steps, its JavaScript-centric code was promising and it was fast. Although still on beta, the “developed by Facebook” label backed it up.
We decided to give it a shot and start using React.
In the beginning, it was really satisfying to do everything using JavaScript: display a chunk of HTML or not, render lists by iterating over an actual array. It was also good to change a variable value and see it propagating to all parts of code via props (one of React components attributes), to break everything down to reusable components and to really stop and think before getting our hands dirty with code. It gave us the consistency we needed to develop maintainable code as a team.
2. React + Flux = ♥
But down the road, not everything is unicorns and rainbows. The first big challenge we faced — and the one that really put us to think if using React was worth it — was a callbacks maze.
Because of its one-way-data-flow nature, a child component needs to receive a callback to trigger a state change on the parent component. It doesn’t seem a big deal until you realize that your child component that is way down the cascade, now needs to update the state of the root component. You have to go over all files and pass the “this.props.updateCallback” down the stream line.
Despite this, we liked React and kept working with it. An effort that paid off: we met Flux, an architecture to enforce and formalize the unidirectional flow of data. It consists of four main elements:
Store: where data (application state) is stored;
Action: triggers a state change;
Dispatcher: manages and routes actions to the right stores;
View: present data in the store and send out actions — here is where React is de-facto used!
With Flux, there’s no need to keep the state on a root component and pass update callbacks to its children. React components get data from the store directly and change the state by calling actions: it’s simple, elegant and prevents you from becoming insane. Flux adds a predictable behavior and some standards to the highly non-opinionated React code.
Recently, I started working on an Angular project. A big part of it was already implemented, so there was no going back, I had to do it. As a loyal React developer, I complained about Angular. I literally cursed it — even if those were the first Angular lines of code I was professionally writing. After all, that’s the way it works: if you love React, you hate Angular.
And I can’t lie to myself, in the beginning I was not enjoying to work on Angular code. Embedding all those framework-specific attributes (or better, directives) to HTML didn’t feel right. I was struggling to get simple things done, like changing the URL without reloading the controller or do basic templating.
The struggle continued when I had problems in my forms because of ngIf directive creating a new child scope for it. Or when I wanted to remove blank fields from a JSON being sent to the server and it removed that data from the UI as well — oh I see, two-way data binding. Or when I wanted to use ngShow and ngHide to display an HTML block and hide another and, for that hundredth of a second, both are displayed simultaneously. I understand many of these issues were my fault –what I want to point out is that Angular is not predictable, it’s full of these surprises.
But of course, a lot of things were easier to do with Angular. The built-in HTTP requests module is really good, as well as the promises support. Another thing that I can’t complain at all: the built-in form controllers! Input fields have default routines for formatting, parsing and validating fields, as well as a good plugin to display error messages.
By using Angular it’s also easier to work with a design team. In our team, there was an engineer dedicated to write HTML and CSS, and Angular enabled us to work together really seamlessly: he would worry about the HTML and a few extra tags, while I’d handle the logic. If we were using React, it’d be at least more challenging for him to write components, since he’d have to learn the basics of JSX (or I’d have to copy and paste his work myself).
Remember the URL-replacing and templating issue that I mentioned before? Nevermind, found out that people normally use a different routing library (ui-router) that does a better work than the standard one (ngRoute). In the end, Angular was not as bad as I expected. Most things that I complained about in the beginning were either because I was forcing the React way of doing things to Angular code or because I wasn’t experienced enough.
4. Bottom line: AngularJS and ReactJS
React uses the native JavaScript functions to allow developers to create reusable components with a predictable lifecycle and unidirectional data-flow. Combined with Flux architecture (or one of its variations — i.e. Redux) it’s reliable, which makes it easier to work with a team on the long-run — without the constant fear of solving a bug and creating ten others. But it might be an overhead when you have people with expertise on HTML and CSS only, since it changes the traditional development flow. It’s also very dependent on the modules you choose to compose your stack.
Angular, on the other hand, focuses on the design simplicity of two-way data binding — what you change on the controller scope will (I’d say auto-magically) show up in the UI. Its opinionated nature saves setup time, by laying some patterns on how to organize the code and making it unnecessary to choose core modules from hundreds of options. However, the same way that with two-way data binding it’s simpler to develop, it’s also easier to create unexpected bugs when changing parts of code in the long run — especially that colleague’s code that hasn’t been touched in the past few months.
And then, what would I choose to build an app from scratch?
For the long term, I, personally, would choose React, using Redux architecture, Axios for promise-ready HTTP requests and react-router. But it also depends on the team experience: if there’s a dedicated person for writing HTML and CSS, I would go with Angular for sure. Both of them have pros and cons and what still counts the most for a maintainable project is the developers’ commitment to write good and organized code.
Settled down from travelling to build some good applications. Feels comfortable developing on both ends, though lately tends to the front-side of the moon.