DEV Community

Jordan Brennan
Jordan Brennan

Posted on • Updated on

Really, why React?

NOTE: I wrote this more than a year ago and decided to not publish it. I'd rather focus on writing constructive stuff (ok, and because future hiring managers might be React die-hards haha!).

But more and more I see React projects that are 10x over-engineered and the worst part is they're all "correct" according to modern React. This has to stop.

I recently got back into React since it first came out and I'm wondering all over again why someone would choose to use this library. Ironically, it's the React team's own words that reaffirm my aversion to it:

We’ve often had to maintain components that started out simple but grew into an unmanageable mess of stateful logic and side effects.
https://reactjs.org/docs/hooks-intro.html#complex-components-become-hard-to-understand

That's the opposite result of what has been so heavily marketed and promoted, and this is coming from Facebook's own engineers. If React doesn't help Facebook avoid an "unmanageable mess", then who does it help? React projects I've worked on aren't much better than the old jQuery spaghetti apps of the past. "But hooks can fix this!" Meh, more of a band-aid than a fix and it's just one of many issues I have with React. Here's my beef:

  • Excessiveness
  • JSX
  • Too many options, patterns, ideas
  • Synthetic events
  • Styles
  • DX is lame
  • Lack of respect for web standards
  • Over-engineering is normal, even encouraged

Let's start with excessiveness...

Excessiveness

I crave tools that simplify my work. If linking to a library, opening its docs, and using standards-based code doesn't work, I'm 98% less interested in that library.

jQuery, for example, required nothing but a <script> tag. The same used to be true for Bootstrap. Today, it's yarning (because npm is not cool enough) and CLIing for an hour before you get to use the thing.

I'm not convinced modern ideas can't be implemented in a way that delivers the amazingly simple experience of the past. Polyfill.io is a good example of a modern use case that avoids the excessiveness of Babel/Webpack polyfills. Frameworks like React should be easy like that.

JSX templates

Instead of HTML or template literals, React templates use, according to the docs, a "funny tag syntax [that] is neither a string nor HTML." This non-standard syntax results in not-so-funny PHP- and JSP-like code. What is funny though is JSX was added as a way to avoid using React's own createElement API. What kind of library adds one weird solution so you can get out of having to use their other weird solution?!

A lot of the template code you would expect to write you can't because "React DOM uses camelCase property naming convention instead of HTML attribute names." For example, the perfectly valid <label for=""> will not work because for gets parsed as JavaScript. You have to use a funny JSX attribute: <label htmlFor="">.

Also, you have to do a funny comment syntax because HTML comment syntax is not allowed.

And don't forget to slash your self-closing tags, e.g. <img />, even though HTML5 dropped that syntax more than 10 years ago.

SVG code can't have namespaces or else "React's JSX doesn't support namespace tags."

Another one I still don't understand and don't want to understand is:

Error: The style prop expects a mapping from style properties to values, not a string.

I'm certainly not a proponent of using the style attribute, but this is just another ridiculous speed bump in my work.

Hopes for changing all the funny stuff have come and gone (see https://github.com/facebook/react/pull/10169). What happens is developers come along expecting to use their HTML knowledge inside React templates - understandably so - and slowly realize how far off JSX really is, and so they of course expect it will get fixed. But the jokes on them! JSX isn't broken, this is by design and is unlikely to ever change unless React introduces a JSX replacement that actually supports HTML.

There's a bunch of these JSX gotchas buried in the docs and I guess this is just one of those things you have to...what exactly? Really, what do developers honestly think of JSX?

Another very big departure from HTML is JSX can pass content to attributes. From the docs:

return (
  <SplitPane
    left={ <Contacts /> }
    right={ <Chat /> } 
  />
);


function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Because of all this specialness you can't easily port JSX. That rubs me the wrong way. Template code should be easy to port because there's a standard to align with: HTML. What a bummer that so many millions of lines of JSX have been written and will not be portable once JSX goes away!

So, to summarize templates in React:

  • Use the funny JSX syntax to avoid createElement
  • Your JSX will turn into a PHP-like "unmanageable mess"
  • You must learn a long list of JSX gotchas, which is worthless knowledge that doesn't actually help you accomplish anything or transfer to other libraries
  • Your template code will not be portable

Not funny.

Functional or Class-based, controlled or uncontrolled, forwardRef, mixins, HOC, Hooks, etc.

I'll let the React docs summarize this problem for me:

If you look at a typical React application in React DevTools, you will likely find a “wrapper hell” of components surrounded by layers of providers, consumers, higher-order components, render props, and other abstractions.

They weren't kidding when they said "unmanageable mess". I appreciate the honesty. Acknowledging you have a problem is the first step to recovery.

The fact that there are so many options and types of components confuses me. This immediately makes an engineer question which way is better? What are the tradeoffs? Perhaps one or more of these are getting deprecated?

When a tool can be used in so many ways it creates doubt in its user. That's why, as the React team admits, "even between experienced React developers [there's disagreement]" on just a subset of these options. It's scope creep and it's exhausting! I want simple tools, like a hammer. A hammer has just two options: pound nails and pull nails. Its design makes it obvious to the user which interface is used for what.

Anyway, React docs say "the simplest way" is functions:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

I agree. Nice and simple. But that doesn't address all the questions and concerns when presented with the Class alternative:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

To avoid reading too much into several contradictions in the React documentation, I'll skip to what I know: the differences between these two options are less now than they used to be since the introduction of yet another option: Hooks.

The docs say Hooks were introduced as a new way to solve for certain needs, like code reuse, and because higher-order components are too "cumbersome and make code harder to follow". For me this just adds to the chaos. Should I now do a function with a useEffects Hook or stick with a class and lifecycle methods? And what benefit do I get from picking the better option? Or maybe there is no better option and this is all a show and no one actually knows so everyone just quietly follows along?

In engineering - software or otherwise - when more solutions are added to address common issues in the original solution it's a sign that original solution was flawed. A big rewrite or abandonment is the inevitable outcome.

I recently read a React post that highlights one of these design issues:

In larger apps you may find that the components you're using to pass props down aren't even using those props at all, but need to pass them in order for children components to use the state.

That's a flaw of the original design and an additional solution - Hooks - was added as a way to deal with it. The original design of state in React was like using URL query strings for session storage. In order for state to persist through a user's session the query string would have to be explicitly passed on every navigation regardless of whether the next page needed those params or not. That would be a very error-prone and burdensome design, and yet that's the design React has. A better design would have provided a way to access state from a global context and that's one thing Hooks are trying to fix.

That's just function vs. class, there's still so many more options like controlled vs. uncontrolled. React's docs refer to controlled components as "tedious" and "annoying". I agree. So why not fix the underlying issues that created the need for these two options instead of adding more workarounds?

Like JSX, is all this mess just accepted without a second thought? Or are people simply tolerating it and moving on?

Synthetic events

Here's another one that just boggles my mind. JavaScript, which React and JSX are supposed to support, has the ability to dispatch custom events on any element. Like this:

// Create custom "bark" event
const barkEvent = new CustomEvent('bark')

// Bind to the bark event in your render function
render() {
  return <div id="dog" onBark={this.handleBark}></div>
}

// Now make the div "bark" 
document.getElementById('dog').dispatchEvent(barkEvent)
Enter fullscreen mode Exit fullscreen mode

Yeah, doesn't work with React.

This is because React has its own events implementation that isn't smart enough to support CustomEvent. Is not supporting core DOM technology normal? Developers are okay with React just not supporting some parts of the internet?

Fine, I'm not being fair. Yes, React can do it...you just have to use two other parts of React (componentDidMount and createRef) and not use the primary feature of React (render):

constructor(props) {
  super(props);
  this.x = React.createRef();
}

componentDidMount() {
  this.x.current.addEventListener('bark', this.handleBark)
}

render() {
  return <div id="dog" ref={this.x}></div>
}
Enter fullscreen mode Exit fullscreen mode

If JSX is funny, then synthetic events are hilarious.

Styles

When I find stuff like this https://github.com/airbnb/react-with-styles I just have to wonder what other devs think. That's A LOT of API to learn just to get some styles; to make CSS work lol! Are we sure this problem hasn't been completely overthought or does React really need this kind of nuclear-scale solution to make CSS work? I don't think it does, but sheesh! there's 62 ways to do CSS-in-JS, so somebody thinks it does.

Meanwhile I'm over here with Vue and Riot getting scoped styles using real CSS:

// Vue component
<template>
  <button>Save</button>
</template>

<script>...</script>

<style scoped>
  button { background-color: lightblue }
  button:hover { background-color: blue }
</style>


// Riot component
<my-component>
  <button>Save</button>

  <script>...</script>

  <style>
    button { background-color: lightblue }
    button:hover { background-color: blue }
  </style>
</my-component>


// Pre-processors are easy too
<style lang="scss">...</style> // Vue
<style type="scss">...</style> // Riot
Enter fullscreen mode Exit fullscreen mode

Developer Experience

No, React is not "just JavaScript" as advertised. In fact, it is so far from it you can't even debug your app without installing special React tools:

"Download the React DevTools for a better development experience"

I think that message from the logs should read:

"We're sorry, but out-of-the-box the React development experience is broken. In order to make it usable you'll need to stop what you're doing and install our browser plugin before you can debug."

Better install the Redux extension while you're at it.

And don't forget that JSX plug-in.

Oh, and you'll need to set up a build pipeline before any of this is even going to work. Better yet, don't even install React. Go get the create-react-app CLI and use that.

Once you have things working, you still run into ridiculous speed bumps when trying to implement the most basic things, like Google Tag Manager.

Meanwhile Riot.js (and others) is instantly usable from a CDN and actually is "just JavaScript", so you can debug your app and inspect the DOM as you normally would.

Standards, portability, and over-engineering

HTML, CSS, and JavaScript are web standards. They will outlive every framework, library, service, preprocessor, syntax, bundler, pattern, corporate-sponsored open-source project, and over-hyped fad that comes along.

When you write JSX and CSS-in-JS you are laying down code that can't be picked up and ported to a new stack. This is a major drawback of any framework that encourages these non-standard solutions. I heard a really good piece of advice from a developer friend who said, "Pick a framework not because it’s popular, but for how much of a legacy mess will be leftover when it’s not." There's a lot of wisdom in that. A great framework is loosely-coupled and respects standards. If you want to change parts of it, or all of it, you should be able to do so without a complete rewrite. Good design works that way.

I think React is one of the worst offenders and one of the worst areas for portability are React functional components because they're basically used as a way to dynamically render HTML or a string. JavaScript template functions are a dependency-free standards-based solution for doing the same thing! On the surface there's only a 3 character difference between these two code snippets, but in reality they are worlds apart:

// Don't
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Do
function Welcome(props) {
  return `<h1>Hello, ${props.name}</h1>`;
}
Enter fullscreen mode Exit fullscreen mode

Even basic stuff like <textarea> has been messed with and can't be ported:

<textarea value={this.state.value}/>

Versus everything else

`<textarea>${value}</textarea>`    // JavaScript
<textarea>{state.value}</textarea> // Riot
<textarea>{{value}}</textarea>      // Vue
<textarea>{{value}}</textarea>     // Handlebars
Enter fullscreen mode Exit fullscreen mode

It just kills me to not be able to use real HTML with React.

What's just as crazy is even when HTML works as expected, the React docs suggest you start with "a small component like Button." Components like that are bad engineering. Button, headings, anchor, and the other 100+ HTML elements should not be recreated as React abstractions! Reasons include:

  • Doesn't respect standards
  • Wasted effort on re-inventing what already exists
  • Needs custom documentation
  • Adds unnecessary point of failure
  • Needs tests and adds test execution overhead
  • Adds browser execution overhead
  • Bloats your bundle
  • Can't be used by non-React apps

The next time you see something like this (it's a real code sample btw) just run away and tell an adult:

<Link href="/about">
  <a>About</a>
</Link>
Enter fullscreen mode Exit fullscreen mode

A popular React framework recently announced:

Applications can now directly import .css files as global stylesheets.

This is ridiculous. One tiny line of regular HTML does the same thing. The React current has been slowly drifting people further and further away from the web platform into deep over-engineered waters.

Performance

The React docs say, "No matter how good a UI library (such as React) might look on a benchmark...a certain amount of work in your components will always cause stutter." Whoa, React used to brag about how insanely fast it is and how the virtual dom, one of React's fundamental technologies, makes it all possible. Now there's unavoidable stutter. Then Svelte and Riot showed how a vdom and its issues can be safely avoided and increase performance.

Performance of a library is always a bit too subjective, so I look at how does that library impact the overall performance of my app. Is the library big, like 10+ kb big? Does it tend to require a lot of extra dependencies? Does it demand a lot of idiomatic abstractions or does it get out of my way and allow for vanilla js? Does it add to the complexity and finickiness of the build process? React is the ultimate complexifier and in this way I find its performance to be unbearable.

Bonus: StrictMode

When a framework has to introduce special “modes” to help you navigate the bad stuff, it’s done. Burnt. End-of-life. Time to cut it loose and push it out to sea.

Discussion (136)

Collapse
lukeshiru profile image
LUKESHIRU • Edited

I'm not a "React advocate" or anything like that, I just use React at work a lot and I also worked with Angular (the old AngularJS and the newer versions as well), Backbone, Vue, Svelte, jQuery, MooTools and so on. Still, I feel that your rant might be slightly biased because maybe you have more experience with other libs/frames like maybe Vue, or Angular for the looks of it. I'll go item by item with my responses, not to engage or anything like that, more to add other point of view to your post:

  • Excessiveness: Besides the fact that you can literally start a project by running npm init react-app, if you want to do things manually, without a build step, you can also create a project, add react, react-dom and htm, and done. You can even import them from SkyPack if you don't want to use npm because of reasons.
  • JSX: I use to hate JSX, because I had experience with stuff that had "template separated from implementation" and I saw JSX as an abomination. The thing is, it actually makes coding components way simpler and more expressive when working with "hyperscript based" libraries".
// This...
const imageAnchor = h("a", {
    href: "https://example.com",
    children: h("img", { src: "example.jpg" })
});

// Is kinda harder to read than this...
const imageAnchor = (
    <a href="https://example.com">
        <img src="example.jpg" />
    </a>
);

// And that's a really simple case.
Enter fullscreen mode Exit fullscreen mode

About attributes like class, and for that are turned into properties like className and htmlFor, that becomes obvious when you understand that JSX is just JS, and that you're not setting attributes, but actually JS properties of the element. If you want to set the class of an element from JS, you use the className property (you could also do element.setAttribute("class", "..."); or element.classList.add("...")). If that's annoying for you, you could use preact instead, which supports using attribute names.

  • Too many options, patterns, ideas: This is, in my opinion, the best thing about React, or any library. If you prefer to write stuff with classes, you have an option for that with HOCs and all that Jazz. If you prefer a more functional approach, you can also write your components like that, using hooks when needed. There are certain things that are a constant, like avoiding two-day data bindings for example, avoiding mutations, and so on ... but those are just good practices pretty much anywhere.
  • Synthetic events: No argument here. Synthetic events are horrible. I understand why they were made (in order to get a consistent event type in any React app, react-native, react-dom, etc.), but I still don't like them at all. The approach preact had with events is far better (but also, preact is mainly for web, not for native).
  • Styles: Again, love to have multiple options. Do you prefer the classic approach with global CSS? Go with it ... maybe a CSS modules? Sure thing! ... having CSS directly in your components is what you like? Then you can have that CSS-in-JS. I understand that for folks coming from frameworks were every question has a single answer this can be confusing, but having the freedom of choosing whatever approach you prefer is something that I see as a pro, not a con.
  • Developer Experience: When folks that work with React tell you "is just JavaScript", is mainly because if you want to solve something with react, generally you can google it as a solution for vanilla JS, and most probably that will work with React. You don't have to do a v-for to loop trough a list, you can just use a map. You don't need a ng:show to avoid rendering something, you can just use a ternary. The solutions generally are things that you can have in vanilla JS. The thing that is more "react heavy" is the actual interaction with the DOM, because React uses a VDOM abstraction in top of it, so you need to use stuff like ref to have access to those elements.
  • Lack of respect for web standards: In this one again, I agree with you. React generally sucks at web standards ... but if we are honest, web standars kinda suck as well.
  • Performance: VDOM will never be as performant as not VDOM, but still if you write your component with performance in mind (memoizing, no internal state, and so on) then that performance difference is barely noticeable in a real world scenario. You can achieve bad performance in pretty much any framework/library, so this is not unique to React.
  • StrictMode: This is optional, and is there to enforce things like not using the deprecated stuff (all frameworks and libraries have deprecated functions and methods, so is ok). I don't see why you say that this is something worthy of push React into the sea.

I believe that's it. Cheers!

Collapse
jamesthomson profile image
James Thomson

Great points. I agree with all of them. I've worked extensively in Vue and a fair bit in React. I think they both have their pros and cons, but one aspect of React that I love over Vue is that it's just javascript. Your point about JSX and attribute properties really drives this home. In JS we have a different style of accessing and settings properties. React leans into this. I also find it far more functional (though Vue is trying to catch up here with v3) - especially due to hooks, easier to work with Typescript, and because most things are just functions, easier to test.

Collapse
buphmin profile image
buphmin

I can see the points as well and they seem valid. The biggest con of react for me, as primarily a backend engineer, is that it takes longer to develop the FE with react vs any other framework or library I have either used myself or worked with others on. I think this is due to the complexity of react as a library and the way it handles data.

Of course my sample size of coworkers and contractors I have worked with over my career is relatively small, as is almost everyone's, so grain of salt. It has just been obvious when I look at a FE task as a BE focused engineer and think "I could do that in 2-3 hours in vue or jquery" and it takes a 1-2 days for FE specialists to do in react. Note I have only worked in larger data driven software applications (no blogs, no content sites, no marketing sites) with high magnitudes of business logic, so perhaps react is not well suited for those types of applications. ¯_(ツ)_/¯

Thread Thread
lukeshiru profile image
LUKESHIRU

I'm currently working for a React project for VMWare (which is really "back-end heavy"), and generally if something takes 1-2 days is a "red flag" (something isn't going as it should). I know for a fact that BE devs prefer frameworks over libraries, but when you have a team that does the BE and other team that does the FE (instead of having the BE team do everything), then things change.
React (and other libraries like it) generally requires to know a little more about FE, than frameworks that do "everything" like Angular, so when BE engineers have to chose something to build the FE, they'll obviously choose Angular.

Thread Thread
buphmin profile image
buphmin • Edited

I know for a fact that BE devs prefer frameworks over libraries

I'm not sure I would say that blanket statement, at least regarding more senior developers. It is all about picking the best tool for the job and what compromises you have to take. For instance for a Go based microservice I picked Fiber over something like Revel because all I needed was routing and the ability to add a few extra custom things.

For my current work my FE team picked react and built the overwhelming majority of it. I would have used either Vue or vanillajs w/ web-components if I had to make a fast decision, otherwise I would spend some time investigating other libs/frameworks for their validity. I already know Angular and Aurelia are a bit too inflexible for my tastes.

Thread Thread
vladimirc profile image
Vladimir C • Edited

I know for a fact that BE devs prefer frameworks over libraries

Hm, why's that? As a back-end developer I would always prefer library over framework when that's an option, because libraries give more flexibility and it's easier to replace rather than stick to framework solutions.

Thread Thread
lukeshiru profile image
LUKESHIRU

Talked from my personal experience (friends of mine had similar experiences as well), but I guess is because they prefer solutions of the type "all-included", so they don't have to figure out anything from the "front-end" when they don't actually care about it. Almost every time I see an app built with Angular, it was created by a back-end or a "full-stack" (which translates to "back-end that knows a little about front-end" or viceversa). Front-enders generally don't like frameworks like that 🤣

Collapse
wolfadex profile image
Wolfgang Schuster

Except that JSX isn't "just JS". If you try to write

function Child() {
  const [state, setState] = useState(...);
  return ...;
}

function Parent() {
  return <Child />
}
Enter fullscreen mode Exit fullscreen mode

vs

function Child() {
  const [state, setState] = useState(...);
  return ...;
}

function Parent() {
  return Child();
Enter fullscreen mode Exit fullscreen mode

you'll get errors. However if you write

function Child() {
  return ...;
}

function Parent() {
  return Child();
Enter fullscreen mode Exit fullscreen mode

then everything works fine. JSX is templating magic that hides what babel is actually producing and what React actually expects.


Syntehtic events in React predate React Native and are due to the state of events in the DOM IIRC. Ember also used to, and might still, use synthetic events for the same reason. Super disappointing because it makes both of them much more difficult to work with.


I somewhat agree about not needing to learn special syntax/a separate DSL like v-for, ng:show, $: { ... }, etc except that JSX is a separate DSL as well with special syntax like htmlFor, className, etc.


I agree with that the performance issues aren't due to vdom, but React itself. There are some vdom frameworks and tools that as performant as if not more than some of the frameworks that boast about being not-vdom.


I do agree that this could apply to most web frameworks. I could say a lot of the same for Ember, Vue, Svelte, ExtJS, etc. I think part of the issue might be from so many people thinking that "just using framework ___" will solve all of your problems. Those who are always looking for or claiming that they've found the silver bullet. I've definitely seen it from most of these frameworks. No acknowledgement that they solve problem A by giving you problem B.

Collapse
lukeshiru profile image
LUKESHIRU

About your JSX example, I don't get where are the errors that you see. If you mean when you run a function with a hook inside of it, then obviously that will produce an error, but I guess you wouldn’t say this isn't valid JS:

const example = () => window.alert("example");
Enter fullscreen mode Exit fullscreen mode

And if you run that in Node you would get an error. There are certain pieces of JS that need to be run inside a specific "scope" in order to work, and hooks aren't different. If you run a functional component without hooks on it, it works as without errors, but when you use hooks, they expect you to run them inside a component structure (similar to the JS example above).

JSX translates to JS, so htmlFor or className is not JSX, is JS. If you want to set the for attribute of an element, or the class you have to do:

element.htmlFor = "id";
element.className = "class";
Enter fullscreen mode Exit fullscreen mode

One pretty common misconception of JSX is that it is "HTML", it isn't ... it looks like XML but it still is turned into JS. You can see it working here. The base logic is that you're not setting "attributes", you're setting "properties", and those two are different ... if you still feel you should have class and for, you can use preact which has an implementation that supports and even encourages that.

About the issues with VDOM, the problem isn't "React", is actually what you do with it. There are apps made in React with great performance, and there are apps made with Inferno with horrible performance. Neither the VDOM, nor the library you use that implements that abstraction are the ones to blame if performance is poor, generally is the code you write using them.

Thread Thread
wolfadex profile image
Wolfgang Schuster

I was saying that the scope/component structure becomes hidden by the use of JSX syntax. This results in errors and unexpected differences in rendering for someone just learning React for the first time. At least this is what I've observed watching others learn React.

I realize that JSX isn't HTML, but it isn't really JS either. Yes it compiles to JS but it's still a separate syntax. We're taught in React that <div className="class"> sets the class attribute on our div and that React doesn't support setting attributes. So while yes they may translate to using properties within JS, it's presented as being HTML like and presented as using/setting attributes. babeljs.io/docs/en/babel-plugin-tr... is actually a more up-to-date transpiling of JSX within React. Your link was true for most of React's life but is a little behind.

The reason I say that the vdom issues are React issues is that using vdom approaches in other frameworks can be much more performant than that of React. This doesn't mean React is necessarily slow, just that it is factually slower than other implementations of vdom.

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

"Just JavaScript" is fake news.

JSX is truly invalid non-executable code. It's not "just JavaScript" no matter how many times that gets repeated. It is as proprietary as any other templating language (don't bore me with semantics about how it's not a templating language).

Also, React's synthetic events prevent valid JavaScript from working.

Collapse
peerreynders profile image
peerreynders

VDOM will never be as performant as not VDOM

In Ryan Carniato's 2020 benchmark Inferno is part of "The Performance Elite" (in many cases it beats Svelte). So VDOM can be fast - if VDOM is what is needed.

I suspect React is hampered by React Native compatibility - and not everybody who uses React benefits from that but invariably is subject to the inescapable trade offs.

Collapse
lukeshiru profile image
LUKESHIRU

Agree! Personally I never felt a "performance bottleneck" because of a VDOM ... generally the problem is with the way the components state is being used. The thing is doing element.setAttribute("attribute", "value") is always faster than doing the diff first. Is also WAY LESS PRACTICAL, but saying that VDOM has better performance than not having a VDOM wouldn't be honest.

Collapse
razzeee profile image
Razzeee

Performance: I think the problem is, that you need to optimize for it in the first place, ideally, you should get it for free. Which other languages also show is possible.

StrictMode: There are languages, that don't have or need deprecation.

Collapse
jfbrennan profile image
Jordan Brennan Author

Thanks for the response! I replied to a similar breakdown (dev.to/jfbrennan/comment/1h0ao)

Collapse
akizor profile image
Daniel Placinta

It's an impressive article and many kudos for it, so many good points.

My curiosity is to see in other comments what experience do React endorsers or evangelists have besides Reacts?! Also, what about experience with programming principles like KISS, SOLID, DRY and many others.

Collapse
jackmellis profile image
Jack

I've used React, Angular, and Vue, plus jQuery back in the olden days.

The key that everybody misses is that react is just a library. You can adhere to SOLID, you can do FP, you can practice whatever architecture you want (I'm a huge advocate of frontend devs learning these fundamental principles). React doesn't have to have anything to do with your application outside of rendering the view layer!

Collapse
peerreynders profile image
peerreynders

The key that everybody misses is that react is just a library.

Then you are just regurgitating what the official documentation tells you.

React's mode of operation exerts exactly the type of design pressures that you would expect from any kind of "framework".

As a result React makes it easy to write applications "the React way" ("React is your application") rather than another way ("React is not your application").

I just recently had a rather lengthy discussion about that fact.

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

On paper, yeah React is marketed as just a library, but in practice React is as huge of a framework as Ember. Once you start, you get sucked in.

Like I mentioned in the article, you can't even insert the standard Google Tag Manager snippet without getting sucked in to the React "ecosystem": github.com/vercel/next.js/issues/160

If you can't see how scary that next.js conversation is, you need an intervention :)

Thread Thread
jackmellis profile image
Jack

I don't want to spark yet another library vs framework debate.

Your point is that's it's "easy" to make an app that's steeped in react-ness, but that doesn't mean that should be the right way.

I've been building apps for years now where react is only a part of the app, I treat react like a library. React is certainly not my application.

This is just another trap that people fall into, then other people copy them, and so on, until everyone just thinks this is how we write "react apps".

I absolutely promise, you can (and should) build applications with react, without react underpinning the entire architecture!

Thread Thread
peerreynders profile image
peerreynders

Your point is that's it's "easy" to make an app that's steeped in react-ness, but that doesn't mean that should be the right way.

Most of React's popularity is based on the perception that using it is "falling into the pit of success" - i.e. it's easy to do the right thing, hard to do the wrong thing. You are describing React as "falling into the pit of despair" - which in a way is what this article is claiming.

React is certainly not my application.

Perhaps you are in the minority. By and large pro-React developers judge it as too much work to keep the UI (React) and the client side application segregated.

And if a React application that is built "the React way" looks over-engineered then the segregated version is going to be worse. At that point one has to wonder whether it is the right tool to begin with.

Thread Thread
jackmellis profile image
Jack

I'm definitely in the minority 😅 and yes a cleanly segregated application requires engineering that would seem excessive on a small app. But your "too much work" comment strikes true with me as I think a lot of developers take the easy/lazy route, and then they wonder why their code is unmanageable further down the line...

Thread Thread
peerreynders profile image
peerreynders • Edited

yes a cleanly segregated application requires engineering that would seem excessive on a small app.

Given the level of engineering you have to invest anyway what does using React buy you? (Other than it being so mainstream that few would question the choice.)

Would it be more work to use something more lightweight (example: HN PWA - live - article).

Thread Thread
jackmellis profile image
Jack

Assuming I'm probably just blind to skme of the jarring aspects of adopting react by this point, I'd probably say it wouldn't.

However, what react buys you is 2 very important things: community support/ ecosystems, and job opportunities!

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

Underscore/Lodash are amazing libraries that offer TONS of value. So is Day.js. So is Riot.js. But no one ever thought of an "Underscore community" because good tools don't require a whole community to support you as you attempt to use it. The best tools are simple, self-explanatory, and effective on their own. React is not that, so people depend on community support.

A large ecosystem is not a benefit. It is a sign that the library is too finicky and non-standard to play nice with the thousands of other libraries out there, hence all the special React versions of those libraries. React's weirdness and excessive ecosystem is exactly why I couldn't get the standard Google Tag Manager snippet to work (same issue and hilarious thread where React devs try to figure out how to make a little snippet of standard code work inside Next.js github.com/vercel/next.js/issues/160).

Yes, job opportunities. When hiring managers don't know anything about frontend execpt the app was written in React and so they need a "React developer". This is not good for anyone!

Thread Thread
peerreynders profile image
peerreynders • Edited

However, what react buys you is 2 very important things: community support/ ecosystems, and job opportunities!

Completely understandable from a personal perspective - but potentially damning for the assessment of the industry's maturity when overall, real cost/benefit of the tool solving an actual problem barely influences the decision.

Thread Thread
jackmellis profile image
Jack

I wouldn't say they barely influence the decision. Just pointing out that at the end of the day, in any language, framework, business, whatever, there is more "real world" stuff than just pure programming pros/cons.

However I also still stand by my opinion that there's nothing wrong with react as a library, we just don't always use it in the best way. I mean, I've seen some pretty disgusting stuff made with just jQuery, far worse than any modern framework 😂 We as developers should be thinking about the tools we use, rather than assuming the authors will hand hold us or force us to do stuff the "right" way - which itself is super subjective

Thread Thread
jackmellis profile image
Jack

Okay. I think using an active community as evidence that a library is poor is not the strongest argument but okay.

What you're talking about with 3rd party libraries though is part of the problem with people's understanding of react. They think everything must be react-ey. Everything must now be a component, or a hook. So library authors go in with highly coupled implementations when really we'd be fine with a vanilla js implementation that can be easily tied in to any app whether it uses react, jquery, whatever.

I've used gtm with no issues, mostly because I didn't try to jam I into my react code, I dealt with it thoughtfully and carefully and developed a solution that wasn't a react component or a hook.

Thread Thread
peerreynders profile image
peerreynders • Edited

We as developers should be thinking about the tools we use

Tools should support good practices (best practices are context dependent). Also tools go out of date while the fundamentals don't. Yet there seems to be a contingent of the community who is practicing some kind of "productivity cult" that pays little attention to the quality of their output while continually bypassing the fundamentals of HTML, CSS, JavaScript and (particularly) browser APIs in favor of investing more and more into techniques that are only valuable within the React ecosystem.

React's use rose with "native-envy" - the pursuit of a native-like experience in the browser with SPA. But MPAs have legitimate use cases - in fact most use cases would likely be better served with an MPA (Return of Multi Page Applications).

I remember a time when some job requirements listed "JavaScript (not jQuery)" and am wondering whether "Web Developer (not React)" is in our future.

Thread Thread
jackmellis profile image
Jack

Maybe one day, I'm all for change when something genuinely better comes along. I think web components will one day make react etc. at least partly obsolete. And I think we're surely all excited about the possibilities of wasm right?

However from a personal point of view, where I've spent several years developing, honing, and investing in my skills as a senior level react developer, any large sweeping changes bring with them the prospect of throwing a lot of knowledge and experience in the bin! I suppose this is what happened with jquery though?

Thread Thread
jfbrennan profile image
Jordan Brennan Author

Yeah, React is jQuery in many ways now. It's one reason I avoid going all-in with a framework anymore. I've learned to keep it vanilla and flatten out dependencies as much as possible. Vue gives me a solid structure and data reactivity and I don't want to use it for more than that.

Thread Thread
peerreynders profile image
peerreynders • Edited

I think web components will one day

Update - article: About Web Components.

I got into Web Components about 2 years ago. There are some parts of the spec that will remain useful but:

  • They dropped the ball by ignoring (potential) SSR of web components. It is possible to write progressively enhanced components (in lieu of partial hydration) but I doubt that will become a common practice.
  • Other parts like the shadow DOM I don't see surviving in the long run (Eshewing Shadow DOM) - they'll likely go the way of applicationCache.

And I think we're surely all excited about the possibilities of wasm right?

What most people overlook (especially client Blazor proponents) is that most environments need a fairly hefty runtime to do their work which adds a considerable weight to the transmittable payload considering current budgets given that personal computing is moving steadily from desktop to wireless handheld devices. Also currently each web worker would need a separate copy of that runtime in memory taxing mobile device resources even further.

So WebAssembly will benefit certain niche applications, particularly in corporate environments but in terms of the public web it's more likely limited to performance optimizations implemented in C/C++/Rust which have a fairly minimal "runtime". So in the end WebAssembly will have much less of an impact than people are currently hoping for.

I suppose this is what happened with jquery though?

SPA happend.

People were actually looking for ways to keep jQuery (or any kind of DOM dependent technology) in check - Segregated DOM.

jfbrennan profile image
Jordan Brennan Author

MPA at a certain scale for sure! I've been met with more than a few blank stares when making such a proposal. "But React SPA is The One True Way" 🤖

Collapse
akizor profile image
Daniel Placinta

I agree with "react is just a library". Correct me if I'm wrong, it becomes a framework once you start using packages react-driven to extend functionality, like state management or routing or SSR. Although React is used for actual render, you start to develop backend-ish code to handle the functionality mentioned. It wont become loosely coupled (SOLID) code once you dive into these. Also, the situation above could become cumbersome when you're consuming basic API processes or having API limitations and you end up tweaking more in frontend.

If we stop at React alone and consider it just a library, we should stop at basic frontend tooling. If we go beyond that and transform everything according to it's own ecosystem, sorry but I'm not willing to complicate things like that.

Been developing since jQuery/Prototype/Mootools/GodKnowsWhat long forgotten era. I've always felt simplicity should be the natural way of developing. Unfortunately, React doesn't tick that. These are my two cents.

Collapse
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

I've seen lots of anti-React sentiment lately and I just don't get it. React is an excellent framework. Just as the JS ecosystem reached some level of maturity with React, developers now seem to be rather keen on jumping ship and chasing whatever new toys the ecosystem has to offer. Framework frenzy appears to be back in full swing and it's not healthy at all.

Excessiveness

You didn't actually mention any problems here. Instead, you referenced other libraries and technologies like jQuery. What in particular about React do you feel is excessive?

JSX
What kind of library adds one weird solution so you can get out of having to use their other weird solution?!

A good one. It's called syntax sugar. You create a library with low-level utils that allow developers to programmatically hook into your system and do low-level things if they need to. In the case of React, those low-level utils are just wrappers around native DOM methods: React.createElement instead of document.createElement, for example. But as a library maintainer, you also acknowledge that most users won't need to get their hands dirty and that the most natural way to create UIs is declaratively. Hence JSX.

Too many options, patterns, ideas

Well, for one, this is true for nearly every conceivable framework. But more importantly, this isn't actually a bad thing. It's a sign of a healthy framework that's so usable and generic that it allows for myriad standards, patterns, and practices to emerge. Some are better than others. The point is that your team has the freedom to pick the patterns that suit your workflow and needs.

Synthetic events

Not an actual problem. Synthetic events are a key part of React's wrapper DOM. I've also never personally had to deal with them.

You mentioned custom events, but is there any practical situation where the code sample you showed would make sense? You usually won't rely on native DOM methods to get a particular node and dispatch an event like you showed here:

// Now make the div "bark" 
document.getElementById('dog').dispatchEvent(barkEvent)
Enter fullscreen mode Exit fullscreen mode

You can use pubsubs, plain old callbacks/props, and other patterns to get around this, or just lean on a state management lib to dispatch events.

Styles

I don't see the problem here. React has lots of options for styling because it imposes absolutely no restriction on what you can or cannot do. Plain stylesheets, stylesheets and CSS Modules, styled-components, styled-components and CSS modules, inline styles as JS objects, and, my personal favorite, styled-jsx. It goes back to the "problem" of having lots of options and patterns. Every team is free to use what it wants. That's a good thing!

DX is lame

I'm not seeing any real arguments here. React is just JavaScript.

Standards, portability, and over-engineering

Ironically, the template string example you gave already exposes you to invalid HTML/escaping/XSS attacks that React mostly takes care of for you. If you want to build robust components, you're at some point going to have to reinvent the wheel.

Components like that are bad engineering. Button, headings, anchor, and the other 100+ HTML elements should not be recreated as React abstractions!

Why not? Every app is an abstraction in the sense that it takes atomic components and uses them to create bigger components. The beauty of creating custom components around native DOM ones is that you can style them and control their behavior consistently rather than always having to override those styles/behaviors on a case-by-case basis. Rarely do you ever take something that a library gives you and use it as-is, in its undecorated form—often, you need to customize the most atomic components and tailor them to your specific needs. There's absolutely nothing wrong with doing this, and it's not even a React-specific practice.

Bonus: StrictMode
When a framework has to introduce special “modes” to help you navigate the bad stuff, it’s done. Burnt. End-of-life. Time to cut it loose and push it out to sea.

developer.mozilla.org/en-US/docs/W...

JavaScript has a strict mode. It was introduced to help us write better code with fewer errors. Likewise, React's strict mode is specific to the framework and is intended to encourage good practices.

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

Thank you for the thoughtful response! Lots of good points and good questions

excessiveness
True, I didn't really elaborate. Sounds like a cop-out, but there's just too much to say.
The excessiveness is all the stuff. So much stuff. Starting with React itself, you have React with React Native and React DOM. Next, you can't just install React. The instructions tell you to setup the create-react-app CLI (aka CRAPP). If you don't CRAPP, then you need to install two React packages: react and react-dom. Wut?! Then, for SSR, you use the special react-dom/server. We haven't even written 1 line of code yet and we're already presented with multiple Reacts, multiple ways to install (there's more than that too), and after it's installed there's a client version of React and a server version of React (which are not the same as native React). Excessive! And we haven't even started to scratch the ecosystem. I'll point to just one example I linked to later in the article: React: CSS in JS techniques comparison (there's 62 69 options!)

JSX
Ok, so you're saying we have the native DOM APIs and React layers custom APIs on top of those and then layers a weird syntax on top of that. Excessive, no?
It would make sense if JSX was better, but it is objectively worse:

<ul if="{todos.length}">
  <li each="{todo in todos}" class="fnt-bold">{todo.title}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode
{todos.length &&
  <ul>
    {todos.map(todo =>
      <li className="fnt-bold">{todo.title}</li>    
    )}
  </ul>
}
Enter fullscreen mode Exit fullscreen mode

Too many options, patterns, ideas
All the different ways of doing things and types of components produce confusion and bad practices. Not having a bad option is better than having one and telling people to avoid it or learning the edge cases where you should use it. It's supposed to be "just the view layer", why is it so complicated? As the React team said, even experienced devs can't agree about best practices because of this. It's a bit synonymous to a Swiss Army knife. Has a lot of tools built in, none really excel, some never even get used but their presence takes away from the rest of the knife experience. Design a new knife!

Synthetic events
Maybe you've never run into issues, but it's a real problem. The problem is more common when using Web Components. So many people defend React with the "it's just JavaScript" argument, but it's not. JSX is not JavaScript, strings and template literals are, but JSX is not "just JavaScript". Same for synthetic events - they should work, but because React is so...excessive with its special "wrapper DOM" as you called it, they don't work with CustomEvent therefore failing the "just JavaScript" test again.

style attribute
The problem is this perfectly valid markup doesn't work:

<div style="width: 10px">...</div>
Enter fullscreen mode Exit fullscreen mode

Like I said in the article, I avoid style as much as possible, but it's just obnoxious that it doesn't work.

DX
I don't know what else to say. The points in that section may be a little ranty, but they are specific and they're really annoying stuff that crinkles the dev experience. Seriously, you can't just use the Chrome Dev Tools, you're supposed to install a browser extension 🙄

Components like that are bad engineering
I've learned from building a few design systems for large, globally-distributed teams that the worst thing you can do is wrap native HTML elements. I'm too tired to get into it, but I understand you're promotion of this is, that's the React mentality I can't align with. There's like an obsession with React-ing literally everything.

Strictmode - oh this is the big one!
JavaScript (ECMAScript) is 26 years old and is a spec that all browsers have to adhere to past, present, and future. Yeah, it's gonna have some baggage that it can't just let go.

React, on the other hand, is a product of Facebook. A product they spend millions on developing and marketing. They are 100% free to fix it, but they choose not to because, imo, they do not want to jeopardize their industry clout by upsetting the React community with a big, bold, breaking version that sheds itself of all legacy funk and brings it up to speed with other libraries. If they did that, too many devs would take the opportunity to switch to Preact or go for Vue or Svelte or Riot or something else.

Collapse
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan • Edited

I don't want to get into a big argument over this, but one thing I do want to touch on is the code sample of Vue vs. React that you shared:

<ul if="{todos.length}">
  <li each="{todo in todos}" class="fnt-bold">{todo.title}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode
{todos.length &&
  <ul>
    {todos.map(todo =>
      <li className="fnt-bold">{todo.title}</li>    
    )}
  </ul>
}
Enter fullscreen mode Exit fullscreen mode

The reason I like this code sample is because it shows just how much closer React is to real JavaScript than other frameworks. Vue decided to invent its own weird syntax of "control flow logic embedded as strings as reserved Vue-specific attributes" and it's downright confusing. React's syntax, on the other hand, is just JavaScript—taking advantage of short-circuit evaluation and truthiness, invoking Array.prototype.map, and returning JSX (which is just syntax sugar for React.createElement calls).

If we wanted to, we could do this to make it even clearer that React is closer to JavaScript than Vue is:

{todos.length &&
  <ul>
    {todos.map(todo => React.createElement('li', { className: 'fnt-bold' }, todo.title })
    )}
  </ul>
}
Enter fullscreen mode Exit fullscreen mode

Voila, there's nothing React-specific here anymore other than the namespacing and the fact that createElement takes prop/children arguments. But it's all just function invocations.

Just something to consider.

Thread Thread
jfbrennan profile image
Jordan Brennan Author

The complaints about JSX have never been centered around how close JSX is or isn't to JavaScript. That point is neither here nor there.

The complaints are about how JSX sucks as a templating language because in practice JSX is React's templating language. The alternative is an imperative API, so yes JSX == declarative template language (React docs say "similar to a template language" because it is).

So, comparing that simple Riot template (that's Riot, not Vue btw) to the same React template, I would take Riot's (or Vue's) proprietary syntax over React's proprietary syntax any day. Reasons include:

  • Less code
  • Real HTML, so you get to use the knowledge you have and not waste time on a bunch of JSX "gotchas"
  • Fancy stuff like if and each are dead simple and HTML-like (so HTML-like IDEs see them as valid HTML)
  • And oncustomevent works because Riot is "just JavaScript" 😜
Thread Thread
lukeshiru profile image
LUKESHIRU

The thing is, JSX is more like a superset of JS, not a templating system. Let's say is closer to TS than Handlebars.

Collapse
lukeshiru profile image
LUKESHIRU

The thing is, this:

<ul if="{todos.length}">
    <li each="{todo in todos}" class="fnt-bold">{todo.title}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Is farther away from JS than this:

<ul>
    {todos?.map(todo => <li className="fnt-bold">{todo.title}</li>) ?? (
        <li>No todos</li>
    )}
</ul>
Enter fullscreen mode Exit fullscreen mode

Unless I understood you incorrectly, you mentioned in your post that "JSX is not JS", but then you compare it with the templating system of vue, which is even further away from being JS (not to mention that vue has support for JSX as well).

I kinda get where are you coming from, but I believe you also got a response to the question in the title of your article as well: Why React? Some folks just pick it because is "popular", some others because it makes more sense to them than stuff like big frameworks with "all the answers" (I know folks that know Angular, but they don't actually know JS nor TS, just "Angular" -_-), some others because they see JSX as something great (I personally don't love it, but I understand it and in React and libs like it, it makes sense).

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

Same here dev.to/jfbrennan/comment/1h10c

Also, your version puts a ul element in the DOM when I don't want one

Collapse
dmondev profile image
dmondev

"I've learned from building a few design systems for large, globally-distributed teams that the worst thing you can do is wrap native HTML elements"
Could you please elaborate or point to some resources about this ? I've been looking into web components for a while and got curious about this part.

Thread Thread
jfbrennan profile image
Jordan Brennan Author

Ah, there's a lot to say, so I'll try to be quick. Users of native elements want to and should be able to just use the native element. Wrapping them introduces more problems than it solves.

HTML is a standard. Standards are good because they enable the most number of people to get aligned on something. If you and I both made a date library and it displayed dates, we don't have to come up with a way to do that - we can use HTML (or the DOM APIs). We win, users of our date lib win because it "just works" thanks to the standard.

If I made my date library depend on React to display the dates, well now I made my library more complicated for me and, even worse, more complicated and potentially unusable for a user of my library. We both lose. The only winner here would be someone already using React in their project. As popular as React is, that's still just a fraction of all the web sites/apps that could use my super awesome date library. This is bad.

The same is true for UI components.

The moment you wrap a native HTML element, you have 1) complicated it, 2) potentially locked a user of the element out of built-in features they would normally have access to (like the disabled attribute or something), and 3) made your wrapped element incompatible with anything that doesn't already have React (or whatever non-standard thing you wrapped it in).

Back in the day we used to create UI components with jQuery, and even wrapped some native elements in jQuery. Teams that didn't have jQuery had to bring in jQuery and jQuery had to co-exist with other libs like React. This created problems. The solution is NOT to create components in React because you're still left with the same problem as before: Teams that didn't have React now had to bring in React and React had to co-exist with other libs like Angular/Vue/Riot/Svelte/Aurelia/Ember/Marko.

I should maybe write an article about this...

Thread Thread
dmondev profile image
dmondev

Thanks for this detailed answer, Jordan !
I was thinking about the basics, actually. For example, to create my own modal component, and anything inside it would be displayed when it is activated. That's the wrapping that I was thinking about, that is standard in html, and why I was curious about what you meant by that. Yes, It makes sense, just obscuring standard elements to provide your own and forcing your choice of dependencies on your users doesn't sound good as well. Thanks !

Collapse
ncpa0cpl profile image
ncpa0cpl • Edited

In the example where you compare Vue compoennt with a React component, the React component is NOT objectively any worse than the Vue one. YOU might think that it is worse, but that's purely subjective, you say it's worse, but don't say how it's worse exactly.

I for one think that the React way is much better, and this is also just a subjective opinion. Those preferences are mostly because of what we are more used to, most of my time working I spend writing pure JS and sometimes React so I prefer the React way, you I presume worked a lot with actual Templating Engines so you prefer the Vue way.

I'd like to also iterate over what other people here already said about the "too many options" point. This is NOT a bad thing, quiet opposite of that in fact, that's a very good thing. Having more options, more flexibility is always good. You cannot blame the framework for the developers mistakes.

Collapse
peerreynders profile image
peerreynders

I've seen lots of anti-React sentiment lately and I just don't get it.

Without getting in details, reoccurring criticism along the lines of

avoid coupling logic with presentation, which mainstream frameworks (React, Angular, Vue) unintentionally encourage.

and quote:

We are essentially going back to tying logic and representation; something that we've been trying to avoid over the past decade or so.

and UI as an Afterthought

is being wilfully ignored by the community behind the rhetoric of "React is a library™ so you don't have to write it that way" because "React is unopinonated" - when in fact React has a clear opinion which can only be countered with deliberate effort, time and determination - which most instructional materials remain silent on.

I used to say that "React is the new jQuery" but I think I'll have to switch to "React + JSX is client side PHP" given how Ramus Lerdorf recounts PHP's early days.

Collapse
jfbrennan profile image
Jordan Brennan Author

I second that advice from David K. and suggest the same for markup and styles. I simply pretend I’m not actually using Vue as I write all my code until the moment I need Vue. Its SFC magic and data reactivity are all I usually need it for. Same goes for Riot. The second I’m back in React it’s React almost every line of code. I’m like, “Move, React! Get outta tha way!!”

Collapse
ecyrbe profile image
ecyrbe

Hello, thanks for taking the time to write this rant.
I want to point at some missconceptions about React.
React is not a component templating library. Vue, Svelte, Marko,... are. So obviously JSX is is not an templating syntax and certainly not an HTML templating syntax. JSX is an extension of JS syntax to make writing JS to React Virtual DOM rendering easier.
So tour title JSX templates is missleading.

JSX is a JS extension, not an HTML template engine. This means JSX is precompiled to JS, then JSX knows nothing about component context, where a template engine does. Template engines are more powerfull to optimize what to render at a high level (before Virtual DOM merge) where JSX has to go all the way down the road to know if it should re-render a sub component by running it's JS code. Where a template engine, being declarative, can understand what to render before hand.

Collapse
jfbrennan profile image
Jordan Brennan Author

Thanks for reading my rant, although I like to think it's less rant and more objective evaluation, but probably just a rant!

I have never ever heard anyone say something like this:

React is not a component templating library. Vue, Svelte, Marko,... are.

I'd say React is definitely the same as those libraries. The difference being React sucks at the templating part because people hated createElement so Fb mixed JavaScript with XML in an attempt to provide something more "familiar". But maybe I'm missing some nuance even though React is "declarative" and "component-based" like Vue et al. Can you elaborate some more on that point?

certainly not an HTML templating syntax

I know people like to say that, but then 80% of JSX code out there is legit HTML, so what does that tell us? The other 20% being all the garbage I mentioned above. Whether anyone at Fb will admit it or not, JSX is in practice an HTML template syntax, the worst one of all time :)

Collapse
ecyrbe profile image
ecyrbe

There is a huge difference between Vue and React, even though both are component libraries.

Vue has a real templating system, meaning, that the control flow (if, loops ...) is declarative... whereas in React, the control flow is made in javascript, it's not declarative... it can only be interpreted at runtime (for each render), with no chance for optimisation.

JSX is just syntactic sugar for createElement (no templating here), whereas Vue has a full integrated template compiler that knows about control flow, component context (props change) and can optimize what it renders.

Hence, not a template syntax engine, even though it looks like one. Hence people expecting it to be a template system, find it ugly.

Now to be quite frank with you. Having used a lot of component libraries, React is the one i prefer using for now. No stockholm syndrome here.

Why ? It's all about writing business code, i prefer using react hooks. It's simple, it's clean, it's composable, it's reusable.

Just compare this :
github.com/jfbrennan/m-/blob/maste...

with this :

AutoComplete = (props) => {
  const [textState, setTextState] = useState('');
  const [completions] = useAutocomplete(textState, props.AutoCompleteSource);

  return (
    <div>
      <input
        type='text'
        value={textState}
        onChange={(e) => setTextState(e.target.value)}
      />
      <div>
        {completions.map((val, index) => (
          <p key={index}>{val}</p>
        ))}
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

I known i can maintain the second one... the first one, maybe , with pain.

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

Thanks for clarifying. I know what you mean about the technical differences in "templating", however irl the library's implementation doesn't matter to a dev does it? Part of building components is writing markup of some kind and that's the role JSX plays. Compared to other markup solutions - true template engine or not - JSX imo is the worst.

As for comparing a React component to a Web Component it depends on the purpose of the component. WC have zero dependencies, are faster, and can be shared across all of your companies web projects. Also, your code above doesn't cover half of the use cases the M- autocomplete does. If it did, yes it would probably still be less code and maybe more maintainable and it should because it depends on a 40kb library!

Collapse
aliakakis profile image
Antonios Liakakis • Edited

JSX is not an official W3C standard like HTML unless something changed recently. Learning JSX first is a costly mistake for any aspiring web developer career and will also leave you with bad habits and an erroneous sense of what is actually HTML.

Collapse
ecyrbe profile image
ecyrbe

Where did i say JSX was standard? Learning React is not a costly mistake, because in today's world, it will earn you more jobs than just knowing HTML/CSS. Maybe you don't like it, but don't fool yourself. The frontend market is dominated by React.

Just look here, at dev.to. The majority of junior dev are doing React, and the majority of hiring managers, are hiring for react. That's part of the rant of Jordan.

The market is flooded by React and no clean alternative is really emerging. Sure, there is Vue. But vue is not without it's own mistakes.

Thread Thread
aliakakis profile image
Antonios Liakakis • Edited

As I said if you need to put food in the table React is the way to go.
But being the best option? I wouldn't go that far. Moreover, NO Jordan's article is not a rant but exactly what is wrong with today's front end market. The majority of juniors dealing with React most probably are not aware of the basics and that is sad not something to celebrate. Moreover, using junior devs as a measure of the success of React is quite strange. How can you accept the opinion of someone just starting for an expert one? The majority of hiring managers are just following the hype and marketing therefore I wouldn't count there acumen when it comes to front end. The market is flooded with React for all the wrong reasons. Vue has its mistakes but surely less than React.
But let me say again. If you want to get a job learn React but hope you will not hate development in the process.

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

You're right about learning JSX - it doesn't hurt. But you got to get out of the bubble. There are TONS of clean alternatives already widely in use and growing in popularity every day.

Also, because I was once a junior dev I do not take any queues from what jr devs are doing :) Juniors flock to React for all the wrong reasons (#1 being it's the most popular...because it's the most popular)

Collapse
jackmellis profile image
Jack

Although these are all good points, the majority of them fall on to us developers.

You can write a clean, elegant, well-structured react application. The problem is the majority of react devs don't know (or care?) how to.

The react documentation (which admittedly is not the best) is full of apologies; not for react being a terrible framework, but for people absolutely butchering it and writing awful code with it for years and years.

On other hand synthetic events are just terrible.

Collapse
jfbrennan profile image
Jordan Brennan Author

True, some of it does fall on the user of React and the community for whatever reason accepts and even encourages grossly over-engineered solutions (they can't even see it's bad anymore), but look closer and you'll see there's very little a React dev can do about:

  • All the required tooling and build dependencies
  • The pitfalls inherent in JSX
  • Sheer number of built-in ways to do things
  • Working around synthetic events (like you said)
  • Style attribute fail
  • The incompatibility with Web Components

And I know the article was pretty long, but one point I made at the start was even Fb engineers admit React projects often "started out simple but grew into an unmanageable mess", so it seems anyway that not even the most experienced React devs can avoid "butchering it".

Collapse
jackmellis profile image
Jack

I've certainly done this (many times, and with other frameworks as well), but it doesn't have to be this way. I feel quite comfortable with my most recent react applications. They're enterprise sized, but organised well enough, and loosely coupled enough from react, that I can look back at code I wrote a year ago, and confidentially understand what is going on.

It is possible. But like all programming, it is too easy to develop bad habits, or let things get out of control.

Of course we don't know if the Facebook devs added this documentation in order to empathise with users that fall into these traps. Or maybe even the geniuses at Facebook get I bad habits too!

Collapse
miketalbot profile image
Mike Talbot • Edited

You make some good points, I for one would much prefer to use Svelte but then that's not actually Javascript. The React "it's just Javascript" is looking at the output of any React component - nothing gets parsed, it's just a function you can call. JSX isn't claiming to be html, it's as you point out, just some sugar and I'm glad of it existing when I'm coding in React, but it locks you in and that's "meh" to me too.

We did a trial a couple of years ago of Angular, Vue, React and Svelte to create our core template app. Of those Angular just couldn't support the dynamic feature set we wanted. Svelte was considered (by others, I'd released a Svelte app) too new and untested, Vue was way slower than React at supporting a core feature of our platform and so we ended up with React and I've learned to live with it. The biggest problems being the "14 ways to do everything".

I came to React after "Hooks" and apart from a side project years ago, I've never used class components and I don't like them. Reactivity works well with hooks but it's not Svelte. I do think you can organise a React code base well and I do think you can produce powerful and performant solutions by reasoning with a few simple hooks.

Synthetic events are a nightmare and massively add to the bloat of React - just look at Preact and the benefits it brings to size etc.

Collapse
daweet profile image
Numbnut • Edited

Thank you for putting to words everything I should be able to say when people ask me why I hate react.

I see no mention of lit-element in the post or the comments, you should check it out. It's more minimalistic than riot or svelte, and uses template literals to make web components.

And a shameless plug - if you want all that, with an even simpler API and no compilation steps works-as-it-is in the browser, feel free to check out my frontend library YoffeeJS :)

Collapse
jfbrennan profile image
Jordan Brennan Author

lit is good! so is hyper. I'll check out Yoffee, thanks for sharing!

Collapse
daweet profile image
Numbnut

Hyperapp or hyperhtml? Both are pretty cool.

Thread Thread
jfbrennan profile image
Jordan Brennan Author • Edited

yeah played with both. almost used hyperhtml for a design system

Collapse
auroratide profile image
Timothy Foster

HTML, CSS, and JavaScript are web standards. They will outlive every framework, library, . . .

I love this quote. This is exactly why nowadays I stray away from synthetic JS solutions. Turns out, I like having accessibility out-of-the-box and not reinventing HTML/CSS : P

Collapse
hamishwhc profile image
HamishWHC

I agree that React has many issues. You've done a good job of pointing them out. But I have to ask you why you think React trying to improve itself is a bad thing. Yes, React has several ways to manage state and component lifecycle. The old ones had problems, and yes you'll have to learn about the new ones, but surely it's better to have them than be stuck on the old version? Especially with your concerns of legacy messes, these new capabilities allow developers to write new code and slowly convert the legacy code as needed. For new projects, you can just avoid the old techniques.

On compilation: I've never worked with Vue or Riot myself, so forgive me if I'm wrong, but my understanding is that Vue works with .vue files and Riot works by defining web components like in your example in the Styles section of your article (Checking the Riot docs, a compilation step is needed. It can be done in the browser, but that's a dev tool and not good for production.). Both of these require preprocessing. You can't act as though React is intolerable in this aspect if you use the same.

On your bonus strict mode point... you do know JS has a strict mode right? :P

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

I respect that they're trying to improve it, definitely a good thing. What's happened though is new "better" solutions are layered on the old "better" solutions which are layered on older solutions. You eventually have to admit the original was kinda gross and no amount of band-aids are going to hide all the warts. The need for introducing StrictMode is a clear indication of the situation.

But honestly, I take what I just said back. Fb has invested millions into building and marketing React. The image and social credit has been valued more than React itself. If that wasn't true, they would have cut a major breaking version and abandoned all the dumb stuff, including JSX (interesting thread about that). Idk, but my guess is the core engineers would have loved to trim React down, clean it up, and modernize it (HTML, custom events, Web Components...Hello?!), but the product and engineering leadership wouldn't allow it because they were afraid React's fame and glamour would take a big hit.

Collapse
ivanjeremic profile image
Ivan Jeremic • Edited

What you don't understand is that I'm 100 faster then you building apps using react, so only because you can't grasp or learn JSX doesn't mean others can'. Another misunderstanding you have is JSX must be same as HTML but no! It's a new language that allows you to write JavaScript UI code compile it and spit out valid HTML thats why it is called JSX and not HTML. At this point it would for you be just easier to not use it instead of writing this post, or if you are soo mad that people build fast apps with it and make money but you aren't because JSX is so complicated then you should maybe buy a course take a shower again and try it one more time.

Collapse
jfbrennan profile image
Jordan Brennan Author

I grasped JSX. And then I dropped it like the snake that it is.

It's just as bad as JSP and PHP of old, maybe even worse because those didn't have any hacky htmlFor or className or defaultChecked etc. attributes. But if JSX makes you 100x faster, definitely use it.

Collapse
aliakakis profile image
Antonios Liakakis

It not about understanding but learning something ONLY useful to React and not an official standard.
The libraries I like are the ones you can remove and your HTML can still render itself without any console errors. Currently I am aware of two such libraries, KnockoutJS and AlpineJS. But do you know what I am reading? React is for complex apps the rest for simple ones. That is the biggest marketing win of React. They somehow convinced people that its for large apps. You have people believing that if an app is not comprised of convoluted code and a large package.json or thousands of lines of codebase, then its not performant or successful. I even read a person asking the knockout team if the lib is still supported with the maintainer saying that the lib is currently so stable that few bugs if any are being mentioned. Then you have React who is trying to fix performance issues with so called new ways like useMemo or memoization and hooks. Concepts that were already part of software science but treating them like something new. So you end up with a bunch of shitty packages react, redux, rxjs(OMFG), sagas, thunks, formik and god knows whatever other crap, in order to build a form. By the way read about notion.so performance issues because of React 3perf.com/blog/notion/ where they had to run into hoops to achieve this.

Collapse
ivanjeremic profile image
Ivan Jeremic • Edited

Why can't you just use KnockoutJS and build apps instead of ranting online how bad React is?

Thread Thread
aliakakis profile image
Antonios Liakakis

I would say we are doing constructive criticism instead of ranting. But whenever anyone is criticizing React its considered ranting.

Collapse
aliakakis profile image
Antonios Liakakis • Edited

I have written an article like this 4 years ago. Finally, other people like yourself are also writing the same thing and I believe that slowly the community learns from their mistakes.
Every React project I was part in was a mess of spaghetti code and over engineering. I was in a startup where the lead front end was a resume/hype driven engineer type. His idea of a React project was so bad that other devs were saying "I don't know how the whole thing works I just write it and try to make it work." He also added TS, rxjs etc for a dashboard app which could be very easily be done with simpler tools. The lead wrote a 130 lines of code which in essence was an axios call of 5 lines.
React has made most devs I know completely oblivious to html/css, in such degree were I met mid level devs telling me they do not know how to style a checkbox without JS or React.
Funny thing is that all the pros of react various fans will throw at you are marketing text from the react site or the site promoting the new way of doing things because all these years we were doing it wrong e.g Redux, sagas, rxjs etc.
By the way hooks are actually crockford objects. But good marketing and a name change does wonders.
But as always if you need to provide for your family and need a job React will give you that.

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

Yours is no doubt a story most teams share.

I know that any large app is difficult to keep manageable, even when using cleaner tools like Vue and Riot, but there's this terrible practice I see in React projects where even experienced developers just YOLO with the React ecosystem and turn what's already an engineering challenge into a serious dumpster fire. And they're proud of it! They seem excited about all this stuff. The more the merrier when it comes to React. Problems are not seen as problems but as opportunities to add more stuff to the ecosystem.

It's bizarre and it's changing the landscape of the frontend talent pool for the worse.

Collapse
artydev profile image
artydev • Edited

Hello,

If you just want Javascript for your Frontend dev
try DML
Here is a simple counter with DML

import {button, idiv} from "./dml"; /* <sdtio.h> :-) */

function Counter () {
    let count = 0;
    let value = idiv("0", {style:"padding-right: 10px"});
    let binc = button("inc");
    let bdec = button("dec");
    binc.onclick = () => value.innerText = ++count;
    bdec.onclick = () => value.innerText = --count;
}

Counter();

Enter fullscreen mode Exit fullscreen mode

You can test it here TinyCounter

Regards

Collapse
dthomason profile image
David

You make some valid points. as I was reading it I was often reminded of those frustrating times when learning React and feeling the same type of way. After getting over those hurdles though I’ve come to realize, I love building in React. There’s just something about it, and then with typescript, ahh the code just starts writing itself. Also, I think when you look at some React code if it’s written the right way, it’s beautiful looking, artistic tic in a way as it sways back and forth down your page. And hooks? Those devilish looking things, letting you reach in at any point to do some side computing or whatever you can think of. Probably just my love for JavaScript/Typescript but I love it.

Collapse
jfbrennan profile image
Jordan Brennan Author

Wow, you are genuinely in love with React. Here's to a happy life as you two grow old together :)

Collapse
jonrandy profile image
Jon Randy • Edited

Really don't understand why Riot doesn't get more love. It feels like such a natural way to build components - a logical step up from normal HTML

The first time I saw JSX - I wanted to vomit (still do). It goes against everything that is generally considered good practiice and harks back (like you say) to the bad old days of PHP - where logic and layout were horrifically bound up together in an unholy mess

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

Riot will have its day in the spotlight!!! I look at it sometimes and think the same thing, like "This is just so obvious and normal"

<demo-counter>
  <button onclick="{handleClick}">Clicked {count} {count === 1 ? 'time' : 'times'}</button>

  <script>
    export default {
      onBeforeMount() {
        this.state.count = 0;
      },
      handleClick() {
        this.state.count += 1;
        this.update();
      }
    }
  </script>

  <style>
    button {
      padding: 10px;
    }
  </style>
</demo-counter>
Enter fullscreen mode Exit fullscreen mode
Collapse
linhtch90 profile image
Linh Truong Cong Hong • Edited

I have tried React, Vue and Angular (not AngularJS). I totally agree with your article about the complexity of implementing the React ecosystem. When using React, we need to learn a lot of libraries to create a full-feature front-end solution. When managing a team that developers use different React libraries for a specific solution, it costs a lot of time and efforts to debate and decide which library should be implemented.

Therefore, I decided to switch to Angular for my projects. Angular provides a full solutions for all problems that we can encounter with in front-end development. It is easier for new member to get started and quickly collaborate properly with the team. Experienced developers also could spend more time and efforts to improve user experience instead of wasting into debate about different tools that solve the same problem.

Collapse
jfbrennan profile image
Jordan Brennan Author • Edited

I generally don't like large frameworks like Angular, but I do understand the appeal when trying to get teams aligned.

I've found that's an uphill battle you can only win by losing, i.e. losing team happiness, losing team productivity as some have to switch to less familiar tech stacks, losing time in refactoring. The biggest gains thankfully come from shared services, like auth, and a shared design system, neither of which require anyone to lose, well except teams using React because React is too whack for Web Components.

Collapse
bradwestfall profile image
Brad Westfall

There are so so many things wrong with this post, practically every paragraph I read (stopped reading after about 1/3) 🤦‍♂️

Collapse
jfbrennan profile image
Jordan Brennan Author

Although you didn't read 66% of the article, could you at least elaborate on one or two points that are wrong:

  • Excessiveness
  • JSX
  • Too many options, patterns, ideas
  • Synthetic events
  • Styles
  • DX is lame
  • Lack of respect for web standards
  • Over-engineering is normal, even encouraged
Collapse
bradwestfall profile image
Brad Westfall

Sure, just the response to the first 1/3 was pretty long, so it worked better as a contrast article:

dev.to/bradwestfall/why-react-beca...

Thread Thread
aliakakis profile image
Antonios Liakakis

I just want to point out that beginners should learn the basics first before starting with React. Again JSX is not an official standard.

Collapse
peerreynders profile image
peerreynders • Edited
  • Your JSX will turn into a PHP-like "unmanageable mess"

CommitStrip: A theory about PHP

They weren't kidding when they said "unmanageable mess".

As I stated elsewhere:

And it has never occurred to you that it's kind of strange that a "UI library" needs support for non-visual components?

My pet hypothesis on why React is popular: components are so darn familiar (and therefore comfortable).

"But React is so declarative/functional"

Meanwhile in Elm land:

and Component's don't work within the functional paradigm.

By replacing classes with "functions + hooks" React has merely traded object instances with closures.

Quote

Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object."

So today under the hood React is no more functional than back in the createClass() days.

Then of course components are reusable - though ReuseHasFailed - i.e. nothing is truly reusable unless additional effort makes it reusable (RuleOfThree).

And then the whole "component styles" fantasy. Layout and styling is not component-oriented. There is no "unified interface" between the layout and a block. Blocks are supposed to blend into the overall global layout (CSS Is Certainly Global And That’s Exactly The Point) - not assert themselves as autonomous entities. At most a block should dictate its structure but not its skin (separate structure and skin) - and most component styling solutions don't accommodate that.

Collapse
huytaquoc profile image
Huy Ta Quoc

The examples related to Synthetic events are wrong or missing details that make them actually work.

For example:

  • This
// Create custom "bark" event
const bark Event = new CustomEvent('bark')

// Bind to the bark event in your render function
render() {
  return <div id="x" onBark ={this.handleBark}></div>
}

// Now make the div "bark" 
document.getElementById('dog').dispatchEvent(barkEvent)
Enter fullscreen mode Exit fullscreen mode

should be:

// Create custom "bark" event
const barkEvent = new CustomEvent('bark')

// Bind to the bark event in your render function
render() {
  return <div id="dog" onBark ={this.handleBark}></div>
}

// Now make the div "bark" 
document.getElementById('dog').dispatchEvent(barkEvent)
Enter fullscreen mode Exit fullscreen mode
  • This:
constructor(props) {
  super(props);
  this.x = React.createRef();
}

componentDidMount() {
  this.x.current.addEventListener('bark', this.handleBark)
}

render() {
  return <div id="dog"></div>
}
Enter fullscreen mode Exit fullscreen mode

should be:

constructor(props) {
  super(props);
  this.x = React.createRef();
}

componentDidMount() {
  this.x.current.addEventListener('bark', this.handleBark)
}

render() {
  return <div id="dog" ref={this.x}></div>
}
Enter fullscreen mode Exit fullscreen mode
Collapse
jfbrennan profile image
Jordan Brennan Author

Thanks, fixed

Collapse
omawhite profile image
Omar White

I use react daily for work and generally like using it. I think some of the points in your article are interesting though. Out of curiosity what do you typically use instead of react when you need to write more complex web applications?

Collapse