Let’s start by disclosing this up front: I’m a big fan of Angular. Recently, I had a chance to work with React. I thought: cool, everyone is doing React now, must be really good. But, it was a disappointment, since the cost of using React is high. This post came to be because team-React is either unaware of this or intentionally hiding it. So, I’ve done a comparison here on the things that cost.
Angular has a steeper learning curve
First, lets define what each provide and which is better:
|Tools||Yes (with Angular CLI)||Yes (with Create React App)|
|Server side rendering||Yes||Yes*|
As you can see from the list above, apart from better performance, React as a library is missing a lot of features that you need in order to create something. I’ll go over each one.
Both provide rendering. Well, no surprise – they are both created for UI. Let’s rethink how this affects developers:
Angular uses custom directives, like if, ngFor, ngSwitch, piping for templating. React uses vanilla JS. It is argued that what people like about React is this vanilla JS approach. OK, but is it that big of a mystery what ngIf, or ngFor, or ngSwitch does? If you can write a for loop in JS, you can write a for loop in Angular template. And what about pipes? Is there anything like that in React? In React you can create something like that, but it is a component. If you don’t want to introduce a global (globals are bad, mmkay?), you will violate DRY by providing, let’s say date or currency format, to all components; even those who do not need them.
We all know that React uses JSX to compose the view. Not only that, but extremely popular styling library in React is Styled Components. Here we have 3 concerns in one file:
In order to have styling as per some unwritten rule in React world, one would have to learn Styled Components. And they are a mess. You cannot override them as easily as you would override CSS, and forget about CSS classes. They are a useless concept in Styled Components. If this styles are component specific, you will write these mini styling components on top of the file. One file can end up with dozen of components.
There are other options in React, like using SCSS, but that means you have to own webpack configuration and drop Create React App and use something like Create React App Rewired. Developers just lost tooling, since most IDEs work only with Create React App.
In Angular, you use CSS or SCSS. That has to be in every developer’s toolbox already.
So, in order to have styles and preserve tooling, in React you would have to learn at least one more library.
Each application needs routing, right? Angular has built-in powerful routing.
In React, you have the freedom* to choose which one you want. This means you have to learn at least one, if you want to use routing. The danger here is that people change teams and teams tend to love different things. Chances are they use different routing, so the dev would have to learn new one. Also worth mentioning that Angular router is more powerful than any react router currently available.
In all, learning Angular Router will allow a developer to work with almost any Angular application, while learning routing in React often means that there is still learning to do.
Angular has its own HTTP Client. React depends on community libraries. The problem is, some of these libraries don’t work with server-side rendering. For the rest, it’s the same story as with routing, personal preferences of lead developers and/or architects create a learning curve for other developers and an expense for the business.
Angular forms are really powerful. There is an issue, though – when you want the results of validation outside of the form, but this is just a reminder to keep the form creation as a service, rather than a real, unsolvable issue.
In React, you have freedom* to choose your poison. You can go vanilla JS and use event handlers. My first impression was – “aren’t we over with callbacks?”, but apparently not. If your application is form-heavy, there are libraries to help you. For example, React Final Form. But, this is two dependencies – Final form and wrapper for React – React final form. Then, if you want to use something like calculated form fields, you will need React Final Form Calculate, which is again two dependencies. If you want to have an array structure in the form, you again need two dependencies for React Final Form Arrays. If all 6 dependencies indeed work together, you can validate the form, but only if you find proper and truth-telling documentation on how to do it.
None provide it out of the box. React has Redux as a library, Angular has NGRX. Both have learning curves, BUT, NGRX has a standard way of doing it and for Redux you can use different middlewares – Thunk, Saga, Observable… Each having its own learning curve.
Angular’s animation module has a high learning curve, no doubt, but it is rather powerful. It abstracts all the CSS boilerplate and has a programmatic approach. React has ReactCSSTransitonGroup, now maintained by the community. Honestly, I don’t know how this plays with Styled Components, if at all, but it’s all CSS based. Here React wins.
React has better performance over Angular, without a doubt.
React has Create React App, Angular has Angular CLI, which has a steeper learning curve than Create React App. However, there are other tools to replace it, like create-react-app-rewired, which exposes the configuration to you. When combined with Server Side Rendering, this creates an even higher learning curve, because now you need to see if these are compatible.
Angular has its own, prefered way of doing things. React depends on the community, each having its own rules. This freedom* comes with a subtle cost to the business: each project can have different set of rules and jump-starting a new dev into the project can cost because they all have to learn the rules. All Angular applications look alike, but each React app is different from the other. I jumped into an Angular project and was productive in days, while it took me months to bring someone into a React codebase.
Also, each React team has its own eslint rules. Sometimes these rules are so strict, that make coding really annoying. Declaring a field and never using it is not an error, it’s a warning.
This is usually thrown by React advocates as a feature of React. You won’t see Angular advocates mention Change detection as a feature. It’s like mentioning blockchain to business – they go crazy over it.
It’s not a feature. It optimizes rendering. That should go into performance section, not feature section.
In any case, React has it, Angular doesn’t.
Server side rendering
Angular has platform server and changing an Angular application to use server side rendering is pretty straight forward and well documented. React depends on different libraries that have to be carefully picked on start of the development, like http client library, routing library… Also, a deep understanding of webpack configuration is needed for React.
Let’s now rate features by their cost (where plus is higher cost, minus is lower), and please don’t be too surprised:
|Server side rendering||+||+|
There are other things in React that are not intuitive and harder to grasp, like, portals, providers, forwardingRefs, so the whole case of Angular having steeper learning curve just falls into water just as you need to create anything a bit more complex.
Reusability and readability
This is where Angular shines. It uses dependency injection to provide reuse of common functionality. React doesn’t have such concept and it is left for the developer to decide how it’s done, leading to different ways of doing it – often globals.
When it comes to readability, we can all agree that the code is often more read then written. React has this bad habit of having too many nested levels in the render method. This can get really ugly. I don’t mind seeing this in HTML, since it’s concept is nesting, but when I see it in a programming language, I know I’m going to spend too much time understand it and maintaining it.
Compatibility & Gotchas
All modules are created and release together by the Angular team, ensuring compatibility. Since it’s a framework, there aren’t many gotchas I found in Angular. Since Angular is a framework and written in TypeScript, I never run into issues with Internet explorer (other than performance issues). Angular abstracts low level things, making you focus on providing business value.
In React, I ran into version compatibility issues multiple times. Sometimes, the code works in major browsers, but not in IE. Usually, this means some polyfill for IE is missing. This is all waste of developers time.
Maintenance, testing and documentation
Angular is a full blown framework, tested by large companies, like Google. Any issue is much faster resolved. Documentation is maintained by the Angular team.
React is a library that renders good. Almost everything else is community based. This means that issues are slower to be resolved, tests are conducted by the community. The documentation is created and maintained by the community. One thing that I learned with documentation for React community libraries is that they sometimes can be incorrect, specifying one behavior, while doing completely different thing. When this happened to me, if we didn’t guessed the solution, like my coworker did (it didn’t even cross my mind), I would have waited for support for God only know how much time, creating a cost for the business.
Freedom vs Convention
So far you can probably see that Angular is Convention based while React is Freedom based. Now it’s time to explain why I placed the asterix after the word freedom… In essence, this freedom comes at a cost. In large corporations, the code certainly isn’t standardized. Moving one developer from one project to another requires technical on-boarding, when it should be an easy move. I’m not against new technologies, on contrary. I’m against this hype and I have yet to see React advocates telling about the cost of each project having different libraries, different structure and above all – technical learning curve for each developer that joins.
OK, I’ll admit that I might be spoiled by Angular and don’t want to deal with low level things. Maybe programming isn’t about creating value, but about solving low level issues and constantly learning different technologies to achieve the same things in a harder and more expensive manner and I have been living in delusion all along.