loading...

Why would people hate React (or JSX), but not Vue SFC, or even Angular?

patarapolw profile image Pacharapol Withayasakpunt ・1 min read

Or even, do you hate lit-html?

I mean, all you are doing is either HTML-in-JS, or truly JS function syntax anyway. No real separation of concern here, unless you truly visually separate them.

I think HTML-in-JS is the basis of SPA, anyway.

Discussion

pic
Editor guide
 

I'm glad you asked , LOL. I worked as a professional React dev for about 9 months ( part time ) and I've been a professional Angular dev for over a year.

I hate React, and JSX the primary reason. CSS in JS is another ( not required for React, but prominent ). First, however let's talk about JSX.

Separation of concerns was the ENTIRE reason we decided to put controllers, HTML, and CSS into different files. JSX muddies the waters so much that there are some JSX novels that I've seen and worked with that read very much like a horror story.

Heiker's example is a good example of this. What I love about Angular is that your component's html file is, well, an HTML file. Sure, it uses structural directives and some minimal ( very readable ) interpolation, but it's nothing compared to the spaghetti mess the JSX usually becomes.

When it comes to very complex views, nothing is worse than having to mentally map your way through a React component with endless JSX acrobatics that you have to translate into your mind into a coherent web page. For simple views, it's fine. But in some of the more complex views that I've seen, it's just ridiculous.

There's a reason why Angular tends to be the framework of choice with much larger and robust enterprise applications. It scales better, and it's easier to deconstruct and refactor the architecture as things grow and change. To me, React is beautiful , fast , and elegant for smaller and medium sized projects, but once the projects scale, it can become a Frankenstein very quickly. There's no real universally agreed upon pattern for how React should scale. ( Not to my knowledge ) , where Angular's structure is baked into the framework.

I didn't bring up TypeScript because technically you can use TypeScript with React, but TypeScript being in ALL Angular projects is the other major reason that I love it.

 

The only thing Angular has going for it IMO is that it's very opinionated in how you structure literally everything. That's fine, but it's very limiting, and sometimes you end up fighting the framework to do what you really want.

As for React, it's far less opinionated. In fact, it's not even a framework--it's just a library, so I don't really think the two are comparable.

As for the JSX soup problem, I think you can really chalk it up to a clash of paradigms and a lack of discipline.

React components should be very small, and only concern themselves with rendering the view on the page. That includes layout, data, and minimal logic (e.g. mapping a function over list items) required to render the correct view.

All of the business logic and technical bits like state management should live inside a higher-order function that wraps the component. The Angular equivalent of this is to have a "dumb component" with a service class to manage the business logic.

That's just a design pattern that people need to recognize and use, just like we have design patterns in Angular. It's just that React doesn't generate boilerplate code to enforce design patterns like Angular's CLI does. To me, that's a good thing, and I'm not alone in that belief. But it does open up more opportunities for programmers to do idiotic things.

 

So it sounds like the debate is really about a clash between the more traditional OOP paradigm (angular), compared to a library based heavily on functional programming concepts (react)

 

@jordan Lee , well yes and no.

I suppose you could make the argument that JSX is the end result of committing to a functional programming paradigm as it would relate to view interpolation. I understand that argument ( kind of ), but Angular's method of view interpolation could have been designed to fit within a functional programming paradigm .

In other words, my biggest gripe about React is JSX itself and functional programming does not require you to assemble Frankenstein entities like JSX any more than Angular's view interpolation is inherently OOP. In Angular, having things like ngModels and 2-way data binding make it classical OOP, but those things are not what I'm enamored with. I'm enamored with "separation of concerns" between the view, CSS, and the component. React cannot give me that. Angular can and does. That's why I went back to Angular after doing React for almost a year.

To the other point @austin made about JSX elements being ideally very "small" and modular, I get that too. But what I found myself doing with React was digging through 10 different components whose JSX all hooked into each other. Having to mentally map all of this when exploring more complex widgets and it can get VERY unwieldy. There's a reason why we separate components from views and I just don't like those two things being combined in React.

However, to each their own, and React is very popular so I'm not knocking it at all. If I have to use it again for an important project, I will.

 

Old man yelling at cloud here. I know that JSX can be use for good and has many good things but I'm here to talk about the things that bug me.

Using JSX to render html elements is all good. My problem is when people go beyond that, when they start doing one clever thing after another in the middle of that html.

Stuff like this.

<div className="tag-list">
  {
    (this.props.tagList || []).map(tag => {
      return (
        <span className="tag-default tag-pill" key={tag}>
          <i  className="ion-close-round"
              onClick={this.removeTagHandler(tag)}>
          </i>
          {tag}
        </span>
      );
    })
  }
</div>

Using .map to render a list? That's clever. Using parenthesis and an operator to make sure .map gets executed? I get it, you want to prevent a bug, but why do it there? They could have handle that in another part of the code but they didn't because nothing could stop them from putting that piece of logic there. And that piece of just HTML-in-js is going to get worse if they need to do more clever things in that taglist.

And then we have "renderless components", I do hate those things. It breaks the mental model of using tags to describe the user interface.

<Provider>
 <div className="editor-page">
    <div className="container page">
      /// stuff
    </div>
  </div>
</Provider>

That "Provider" thing, if I can't put a margin, padding or color I don't want it as a tag. And of course this "renderless components" are so flexible that we can do this.

That freaks me out.

 

I don't understand this attitude of "I hate framework X because people are able to do things I consider bad practices."
Every language/framework allows many kinds of bad practices, it doesn't mean you should use them.

 

I don't understand this attitude of "I hate framework X because people are able to do things I consider bad practices."

Did I give that impression? I wasn't trying to say that I hate React, I actually like it. I tried to be very specific on the parts that I don't like.

Every language/framework allows many kinds of bad practices, it doesn't mean you should use them.

While you can always choose the patterns you use, you can't always choose the tools used in a codebase.

 

Agreed on the renderless component thing. I get it and it's purpose, you can do them in Vue, too. In some cases, I don't mind it, but when you're using a component to define the behavior of your router, I just don't understand why in the world you would want to. Defining route logic in your render function just seems illogical to me. What's wrong with doing it like Express/Vue and pretty much every single other framework in the existence of the web? 😵

 

I personally love the declarative nature of handling routing inside the component.

The DOM forms a tree structure, and so does the function call graph of your application. Routing (as a general concept) represents a "forking" mechanism in the middle of that DOM tree structure somewhere. There is a "choice" to branch off in different directions. Since (in React) we are already representing our virtual DOM as a return value of the function call graph, why would we not handle routing in the exact same way, since routing is almost precisely the same idea as a function with a switch statement?

If that doesn't make perfect sense, then I'm at a loss for words...

 

Seems like anyone can do whatever they want - is not a bad problem to have

 

Tell me you're not defending the XML Sort function.

People seem to jump at the chance to defend the indefensible on the Internet.

There would be no good choices without bad ones

 

Vue's Nuxt also have <client-only> (i.e. <no-ssr>).

Good thing, maybe; is that Vue / Nuxt prefers DSL in <template> tag.

 

I'm not familiar with Nuxt. I imagine that <client-only> is also a renderless component. Still not a fan of that type of component.

What I like about Vue SFC is that is familiar. The template, script and style tag is a good mirror to the traditional html structure.

 

Vue and Angular are very good because they impose a certain style by using strict conventions and style guides.

So anybody else can come later and understand your code.

The same can't be said about React, even if it has big companies using it.

Also, my biggest problem when I used it was that it doesn't have just one STORE. But a lot of clones online(easypeasy, mobx, another better management store).

So my question is:

Can react devs and contributors stop forking and working on a single universal store and best practices for it?

 

I know this is old but....

Vue and Angular are very good because they impose a certain style by using strict conventions and style guides.

This is not necessarily true for Vue. Vue is a view library and it is very flexible. Vue doesn't require you to write your code in any specific way. You can use render functions with Vue (JSX syntax sort of like React), you can use .vue files and have nice sections of things, you can use the composition API (which completely gets rid of 'strict conventions and style guides'), or you can import Vue from a CDN and just use strings and objects to render stuff out with templates. I would argue that Vue is actually less opinionated and more flexible than React.

 

Hi @samwight

You are right but, also Vue has this vuejs.org/v2/style-guide/, which will help you keep your code readable and implement some guidelines so you don't take the wrong turn. React doesn't have something similar, so it's easy to get lost quick and your code becomes complex. Best practices with clear guidelines will bing more productivity. Thanks for the follow up

All of the things React either checks for or can be added by a linter (which is included by default on CRA). Check out AirBnb's style guide for React/JSX here: github.com/airbnb/javascript/tree/...

Style guides don't restrict your components from becoming complex or being difficult to manage. All they do is make sure you're not using double quotes instead of single quotes, or using a keyed loop instead of a non-keyed loop. Vue's style guide is a set of lint rules, not a set of strict guides on what to include in your components and how to actually structure your code.

 

Overall, I think the biggest issue I've found with React is it just doesn't have an opinion on a lot of things: routing, state management, logical categorization of components.

The second big thing that I find awkward with it is that it doesn't have a discrete services layer. Prop drilling and context are fine in small applications, but I'm just really not sure that embedding the services layer in the view hierarchy is at all scalable.

I hear a lot of people bashing Redux, and I get it - it took me a while to come to grips with it (no thanks to the Redux-specific jargon), and it involves a lot of boilerplate - but I really think it's better to separate your data access and transformations into totally separate files, detaches from the view hierarchy.

All that said, I have no problem with JSX. It serves as a nice visual distinction between the component hierarchy and any business logic a component might have (unless you mix your business logic in with your JSX - please don't do that).

 

I'm really keen on separating out logic from my view layers in complex apps. The fact that almost most react blogs and docs don't mention large multi-target apps (cli/api/web-app that all share code). #cleanArchitecture

 

Totally agree. It just makes things so much easier to think about.

I still really like React for its composability, though!

 

JSX Syntax is terrible. It reminds me of the old days when we had PHP inside ugly tags. Then we came out with template engines and the world was a better place.

SPA's have this problem generally, with qoutes inside qoutes inside qoutes making terrible to read templates. I prefer clean and simple templates with nothing more than a few capitalized key words inside mustache brackets. You don't need anything else, and anything else more complicated should be inside code and delivered as a value to the view. Languages inside of languages always annoyed me, and for more complex projects it quickly gets out of hand. Your essentially trading the spaghetti code of one kind for spaghetti of another, which then requires you to write ever more complex code to check the code.

It's the sort of design pattern that reminds me of John Stewart Mill's warning about how "The bureaucracy is expanding to meet the needs of the Expanding Bureaucracy."

Vue has the least annoying template syntax, so it's my go to for persona projects.

React as a whole is quite good and I'm a big fan. But I write as little JSX as possible, and when I do, it's almost always an actual value with data-binding instead of a method call to a method call inside a method call. Every time I see an arrow function inside a template I die a little on the inside. And before someone mentions how bad code shouldn't damn a language, I'd like to point out that React design docs actually encourage this pattern.

Angular has a different problem. There are about 5 ways to mark up html elements, to the point that you get that absurd banana-in-a-box syntax for stuff like ngModel, and again you end up with quotes inside of quotes because you have to appease the parser ... rather than having a unified syntax and forcing the parser to appease us.

 

I feel like react often introduces new ways to do the same thing and everybody refactors and updates all their libs to the new hot way of doing things. The most recent addition is hooks, which was supposed to reduce 90% of your code's complexity. Unfortunately, it only makes simple code simpler, everything else became harder and requires you to know the nuts and bolts of react, hooks and javascript. Some argue that's not a bad thing, but it's by no means progressive like vue. Consider all the devs out there whose "first language" is not JavaScript...

E.g the following will execute the useEffect every time it renders if you don't pass the item prop because it is considered new. Imagine setting state in the useEffect, you got yourself an infinite rerender without any sort of error message hinting to the solution, or even the problem.

const { item = {} } = props

useEffect(() => something(), [item])

 

I'm not sure I can agree with your comment about hooks making React more complicated. Of course, if you've only ever written class components and are using hooks for the first time, you can expect there will be some learning curve - as with anything. But I firmly believe the learning curve is worth it. The main points I disagree with:

  • React continuously introducing new ways to do the same thing: I view this in a totally different way. Yes, ultimately React/Angular/Vue all do the same thing - decoupling application state from the DOM. But if the React core team is constantly looking for better ways of achieving this goal, surely that's a good thing? Otherwise we might as well all be using React.createClass still and never upgrading past v3.0.0.

  • The next question then is "are these new ways of doing things better or worse than the old ways?" Regarding hooks, my experience is that they're much, much better than using classes when writing stateful components. By "better" I mean that after becoming accustomed to the style, it is much easier and faster for me to build an app. I can also scan and understand others' codebases written in hooks much faster.
    Additionally, with hooks there's less boilerplate code and React apps written with hooks are technically more performant than ones written with class components.

  • Surely you'd rather have library maintainers who update their packages to support new features, rather than using some npm library which has been untouched since 2014 and doesn't support ES6?

  • I can't comment specifically about the code snippet you provided, but I'm fairly certain React always warns you when doing weird things with setting state that cause infinite re-renders.

The caveat to my favourable opinion of hooks is there's still a couple of things I hate about them: firstly, how cumbersome/hacky it can be to properly add event listeners inside useEffect, and the currently poor solutions for async data fetching inside hooks (although this looks like it will be improved with the next major release).

Feel free to let me know if you disagree with anything

 

I don’t think they outright hate JSX, but rather, they simply prefer a different solution.

 

people who hate Anguvueact, usually they either had to work with a bad codebase using it, or somebody they dislike is an advocate of it.

 

Just sort of musing here:

I actually really like the dev experience in React - it's fun, and who doesn't have fun at work?

However I'm not really convinced that SPAs, as a solution, are really in users' best interest, you know? For things that are actual applications, sure (Jira, Evernote web, Google Sheets, etc.), but for a static content or ecommerce sites... I'm not so sure.

As far as I can tell, it increases load times, complexity, processor use, battery drain, and data usage. That's fine for anyone making a developer's salary, but it makes your site a lot harder to use for anyone who can't afford a current-gen phone or a nice data plan.

 

Agree, but that's another question. I assume/hope that developers using React etc. responsibly, and not for static content leaflet pages and such. For practise ok, but not for end-user-focused products.

Fair point! I've definitely worked with codebases that turned me off an entire platform (Android comes to mind).

 

You use vanilla JavaScript and vim? Well I write everything in machine code, like a real developer

 

Well, I don't HATE JSX or any other markup. It's just a preference. That said, I prefer proper using HTML attributes like class, style etc. Instead of something like className.

 

html belongs to html file! :) react is not my way.

 

I currently know Angular basics and Vue basics and I didn't find the initial learning difficult but when I tried learning react I found it more difficult and I didn't like React's way of doing things. Using vue's sfc was easier to understand for me than using React's JSX (although I prefer the Angular way).

 

React does not separate HTML, CSS and HTML. Vue(for example) on the other hand, at least does.

While both have everything in a single (JS) file, in Vue it is at least separated. At the top you have your HTML, then your JS, and finally, your CSS.

I haven't used React yet, only seen codes, so I said the above based on those.

Also, React has barely any logic in the code IMO, which makes it very hard to learn.

Don't know anything about angular.

 

That's totally fair, and I have no complaints about the architecture of react or JSX for that matter. It's an extremely solid and well engineered library.

Though as a general rule I try to avoid describing anything view related in code, and likewise I avoid describing complicated logic in views. When i build something in any language or framework I try to find a really stable subset of it, and write everything in that and I try to avoid getting clever.

It's probably a good rule of thumb for any SPA framework actually.

 

A "long" time ago people used to put php/ruby with html and let it be generated on server. First they moved it to separate files then they started using SPA. It is in a way better to have application logic like UI stuff and validations run on client as you get scalability for free. However you still need to validate again stuff on backend. Now should be again forget the front thigs and get back to server? I don't think so. Same goes for HTML in JS. I'm more into Angular only because everything is separated. As for Vue i can see the point of having 1 file split in 3 sections. However Angular is slower then the rest and I'm just a backend guy.

 

React is a snapshot from the past in the evolution of frontend work. Over the years it progressively gets in the way of native features and hasn't addressed complexity, so what it offers is increasingly a cost, not benefit. Given the lack of awareness of modern native features and recently released higher level libraries that outperform both for development and users, along with strange polarizations like OO vs FP instead of OO with FP patterns applied appropriately, I'd chalk up this stuff to inexperience. Speaking for myself as well.

I see job listing mention unit testing and nothing about any integration tests and then when looking at their unit tests see it's higher level than unit. Given the performance of end user features are the determination of "it works" and "it doesn't work" I'd say the picture painted is pretty consistent.

I dislike React because it doesn't seem legit and I just find it frustrating to consume a perceive reinvention stuff with heavy marketing. Sure it may look cool and do something useful but why would I bother when something else works better? Just find myself seriously questioning what people are doing when the stuff they output begin to suggest a lack of competency. There's always something to learn, that's just being human, and it also means I can feel free to dislike any/all of these options entirely separate from mixing markup in templates in scripts or whatever.

 

Random observations, without a lot of reflection (and no don't hate, or rather quite like and appreciate anything lit-related so far):
JSX is obsolete and irrelevant relative to natively supported template literals and transformations for backward compatibility.
React imposes unnecessary technical peculiarities/requirements on an already complex range of topics.
DOM diffing doesn't help in the way React does it, LitElement/lit-html performs better in the few cases where this makes a difference, especially relative to proper strategy.
While native Web and DOM APIs have matured React has stagnated and is in the way.
Overall React is the technical debt that jQuery was in times past.
It is odd to see new projects commit to React, except they must not have information or experience with the alternatives (LitElement, Elix, native, etc?).
In exploring using Deno I've come to learn the vast majority of NPM imports for testing, etc are generally becoming obsolete due to its included standard library and the ability to use the same exact API on the front and backend in development and testing.
I don't like the growing complexity in the patterns: tree and component types (also the case in Flutter, etc). Prefer instead to limit this complexity in various different ways.
In LitElement state management is clearer and less cumbersome based on my limited experience so-far relative to React and Flutter. In Flutter the Provider pattern mixed with local state was helpful and similar to various things I found easier to use in my own native Web Components work.

 

I suggest using Webscript: mudgen.github.io/webscript/docs/

This is creating the DOM in Javascript the right way.

 

The website is broken on mobile.

 
 

Thank you. I am making it work on mobile now.

 

RiotJS and possibly Svelte (I don't know it well, but looks awfully similar to Riot) have it right

 

Svelte just force me to use a special extension and compiler. They don't even have full TypeScript support.

Vue also has SFC and a special extension. *.vue's Vetur has decent, but not full TypeScript support.

IMO, when template / DSL is introduced, it isn't HTML anymore.

 

because vue and react has better documentation.