364 comments

[ 3.5 ms ] story [ 29.4 ms ] thread
An aside: This name an logo are incredible. https://bevacqua.github.io/dragula/
An aside: drag and drop doesn’t work on iOS Safari well at all - dragging also pans the viewport.
whenever people make these arguments they fail to mention all the ways in which the platform is deficient and leads to subpar results, unless you...build it yourself.
Yeah, that was kind of ignored in the article and it's definitely an issue for some platform features. Date pickers are another one where it's easy to outgrow the native implementation.
When I tried using <dialog> for the first time, there was one major thing that stuck out to me as a bit of a problem with how it is implemented:

It has become a norm to expect that if you click/tap on the backdrop of a modal/dialog, it will dismiss the modal/dialog. That isn't the case with <dialog> by default, and you need to use either use a hacky JS handler that checks the bounding box of the dialog (because the backdrop click events just end up fed to the dialog element), or use an attribute, `closedby`='any' that does not work on iOS and has spotty support at best in desktop Safari

I feel like it’s a historical accident. In the past the platform couldn’t do it all, and if you wanted a dialog you had to use a library. Developers were trained to reach for libraries when they needed something like a dialog.

Then react came along and all developed learning web development after react had little to no knowledge of the platform. They were taught that touching the DOM was a bad thing to do.

That’s about it. Even now when I advocate for vanilla css I get the side eye and “tailwind and shadcn should be the default”. I get it, it’s what most people are familiar with, even if it’s worse than the platform.

How is tailwind and shadcn worse than platform? It speeds up development by orders of magnitude.
Depends on the criteria, e.g. if dev speed has highest prio, a full blown component lib like Material UI would be superior to shadcn. CSS can obviously do things that tailwind can't, so it is more powerful.
The point of shadcn is you can pull in a component and modify it any way you want. It's always going to be bare bones at the start. Something like MUI locks you into a layout and style that's coupled with the API, and you need to rewrite big chunks of your app if you want to add your own branding.

For me the best middle ground is Headless UI or Bits for Svelte, unstyled and composable but you don't need to vendor code into your repo like shadcn.

This comment is at the same depth of analysis of saying that the only reason for python being successful is that universities started teaching it and then people no longer could do C++
I know you're just meeting the bar, but counterpoint: They're correct. Do you happen to have a deeper analysis above the bar of your own to deny it?

I personally feel they are for the simplest reason that Web Development exploded to the point the new blood and cultural migrants outnumbers and outproduces the old. Those lessons were taught, and kept, the mundane act of googling anything suffixed with "... in React" being the kiss of death that settled it.

It’s funny, the article proceeds to answer the question in great detail: familiarity, level of abstraction, documentation, etc.

I agree with his point that learning to do it yourself can be fun and lead to a flywheel of improvement where the next time you’re faster and the next time faster still.

In the past that was the recipe for success as a developer, nowadays with AI many feel that’s no longer the case.

Extreme apathy towards "learn to do it yourself" is exactly why "AI" is so popular right in programming right now.
It's not apathy towards "learn to do it yourself", it's apathy towards dealing with the recursive fractal of bullshit that is modern software. It's not 2000s anymore, we have orders of magnitude more of nonsense to learn, and learning that is just a waste of life. LLMs finally give us that option.
Nothing prevents you from just using the lower layers of abstraction. I have developed a few games using Raylib and it was really fun.
Yeah, except if we're talking about web development, then the lower layers is not Raylib. It's HTML, CSS, JS with its DOM API, plus whatever other bullshit WhatWG throws in.
Web dev is absolutely a shitshow, but it wasn't necessary to learn all of it to have high paying job. There were plenty of jobs where you could specialize in frontend, backend, infra, data... even subsections of those. And yet a lot of those people still learned the bare minimum they needed. They wouldn't bother to learn the languages they were using every day deeply, and they wouldn't learn their tools deeply (editor, git, etc). I knew plenty of those people. If you were doing true fullstack then you sure, you have a bit of a point, but many people did not, at least at the places I worked.
The last couple of websites I've made have been largely the output of Claude with some instructions to keep to WCAG AAA accessibility standards and to optimize for loading and rendering times, and it's done a pretty decent job. If you're insistent about page weight it will avoid adding JS and React and use to browser-native elements, CSS, and vanilla JS where it can.

I think the problem is that you have to ask, and to know the language to get the result you're after. If you just ask for a pretty website you're getting 800KB of React libraries to render something, and all in AI Beige with Inter as your font choice.

Do you really need to know the language or is it enough to bother asking about improving the loading time or customizing the look?
You need to know.

Here's an isochrone map renderer I got Claude to make: https://benwheatley.github.io/Isochrone/web/?region=berlin&s...

One of the failure modes was it running out of GPU RAM because it tried to allocate (multiple!) pixel buffers on a m-pixels-per-n-real-world-meters basis(!), and repeatedly didn't see the problem with this despite it being a vector graph on a normal screen.

I only even noticed this bug due to another bug where it got the bounding box for Portsmouth badly wrong by including the entire length of the ferry routes to France.

If I didn't understand how to use the JS console, it would have been stuck saying "I can't reproduce the problem"; and if I didn't understand the way computer graphics work I wouldn't have been able to recognise that multi-gigabyte pixel buffers are not normal, nor would I have been able to recognise that in this case those particular buffers were totally redundant.

For one thing, I just genuinely think WebComponents are a badly designed API that is weird and hard to use (how many people are using WebComponents without at least Lit, if not something much bigger?), and React is a relatively well-designed library that isn't really that bloated. There's not really much of a point in trying to argue since this is inherently subjective and people with different values are going to irreconcilably disagree. But, if you don't respect that some people hold this position, we're not going to make any progress towards a consensus.

On the note of <dialog>, I recently tried to use <dialog> in a (React) application, and it did work pretty well, but I also found that in Firefox it is only practically possible to do a fade-in animation, not a fade-out one. That isn't really a critical issue for me, it is just an animation after all, but I find it unfortunate. I also find <dialog> to be a weirdly shaped API too: I don't really hate it, but I don't love it either. It feels awkward.

I find this implicit view that developers that, for example, prefer React over WebComponents are making a suboptimal choice to be rather condescending and not really in the spirit of trying to see things from the other side. Wouldn't you want to focus on the strongest arguments and not the weakest ones? Maybe you've literally never heard anyone complain about WebComponents or Shadow DOM, but if so, I find that surprising. Certainly here on HN, I've seen a fair bit of WebComponents hate.

I do, FWIW, realize that I've particularly focused on WebComponents, which this article doesn't actually name directly. But, I assume we're not talking about ditching React to implement our own component framework on top of the traditional DOM APIs, because that's what React already does...

> I just genuinely think WebComponents are a badly designed API that is weird and hard to use

This was exactly what sprang to mind as soon as I saw the title. I’ve been writing front-end code for over 25 years now, and exactly two things in that entire time have made me miserable enough to think about stopping: Internet Explorer 6 and web components. Every time I try to just “use the platform” it makes me miserable and I end up demotivated and stop working on whatever side project I chose to try again with. And I otherwise like the web platform! I’ve been building with it since there was nothing but the web platform. But web components kill my enthusiasm for it stone dead.

Even now in the age of agentic development, AI trips over all the same footguns in web components that humans do. It just seems like everybody involved has been adding to the standards with “yes, and…” without ever thinking about how it will be used by web developers in practice.

> React is a relatively well-designed library that isn't really that bloated.

I am one of the people who irreconcilably disagree. I think svelte and solidjs are - obviously - technically superior. But it leaves the question of why react is still so popular. I think the biggest reason is all the non-technical aspects of react:

- They have excellent documentation. And have, from day 1.

- They produced videos, sample projects, and all sorts of "getting started" documentation.

- They ran react conferences, teaching everyone who would listen about "1 way data flows" and pretending like they invented FP.

The amount of hype around it made it really feel like the next big thing. Between the very well funded react team and the outside developer community, there was real momentum. People learned it in droves. Taught students. Built websites with it. When react's poor design choices caused issues (and there were a lot of issues), then you were blamed for holding it wrong. (Component classes, state, CSS, hooks, webpack and babel taking ages, big bundle sizes, slow re-renders, and so on.)

By the time the next generation of JS frameworks broke onto the scene, there was a collective moan from the community. "Oh no, not again - we just relearned how to make websites." React was the wave, and in its wake we all had Framework fatigue.

Software doesn't get popular without a lot of work by dedicated people. I really admire the work standards bodies do. But they rarely bother to take the time to produce documentation, videos, tutorials, starter projects, blogs and podcasts and all the rest of that work.

> I am one of the people who irreconcilably disagree. I think svelte and solidjs are - obviously - technically superior.

I don't really think that React is necessarily the best possible library, but there is certainly more to a UI library than simply compiling out the need for diffing. For one thing, I find JSX to be a relatively unobtrusive addition to the language. It is implemented by a variety of things and is a pretty simple transform as far as things go; basically pure sugar, it's possible to avoid it if you want. It could be better designed than it is, but I think it's at least sufficiently general - it is feasible to say, use an alternate library with JSX, like Preact.

Svelte on the other hand by its nature just simply requires a more complicated compiler step to work and deliver on its promises. That's a trade-off. Whether you think it's worth it is up to you, but presenting it as an objectively technically superior design is disingenuous. Superior how? Runtime costs? Sure, but it does beg the question how much. Will a well-optimized Svelte app feel much better than a well-optimized React app?

> The amount of hype around it made it really feel like the next big thing.

We are a really long way away from the hype of React. I would argue that hype stopped carrying React a long time ago. Momentum? Sure, but if something was truly dramatically better, then I think it would have a fair shake at beating out React.

The problem is that the web isn't microbenchmarks and developer experience does matter to some degree, so the trade-offs that seem so good on paper don't always pan out.

I'm not a hater of Svelte. On paper, it is a very elegant idea. However, when I actually tried to use it, I genuinely came out feeling that it was simply not for me, and the benefits it has are not enticing enough for me to continue experimenting. My React apps are not particularly slow or bad at handling huge amounts of data. (One of my apps has no problem handling a file grid of over 1 million items, and in fact, I run into issues with browsers not being able to handle a large enough scroll area long before performance of my React code is a problem. That is good enough for me.)

I should probably be more balanced when criticising react. React moved the state of the art forward when it came out. Compared to the other options we had at the time, it was excellent. But it's not better now. At least not for technical reasons.

> Superior how? Runtime costs? Sure, but it does beg the question how much. Will a well-optimized Svelte app feel much better than a well-optimized React app?

Virtual dom diffing is pure overhead. It increases the JS bundle size (react is big). Vdom diffing is really slow. And it's simply not necessary.

I agree that if you make heavy use of comparator functions, react apps can feel ok to use. But most sites don't do that. Look at the new reddit site. Insanely slow and insanely inefficient. They've improved it a lot since the new design landed. But it's still 19mb of javascript or something, and much slower than it should be. Maybe reddit is only slow because they're holding react wrong. But if everyone holds react wrong, it's react's fault.

If you don't like the asthetics of svelte, check out SolidJS. Solid is aesthetically almost identical to react. Solid - like react - only needs compilation if you're using jsx. The difference between solid and react is that solid only executes component functions once. Reactivity is implemented via fine-grained signals. Solidjs apps perform better, because there's no vdom. The default way to use solid is already fast.

> if something was truly dramatically better, then I think it would have a fair shake at beating out React.

Eh. Lots of old technologies are still in use. Most software engineers don't enjoy learning new frameworks every few years. And react still works fine, even if there are other options today. I think solid and svelte are better, but they might not be better enough to displace react for the average web developer.

If you like react, give solidjs a try. It's essentially "react with signals", which I find to be a significant improvement. You get much smaller JS bundles, better performance and better state management. All while keeping a lot of the best parts of react's design philosophy. It's great.

I mean, prior to React the big Framework at the time was AngularJS 1 - a hellscape of two way data binding.

Talking about one-way data flows was an excellent way to speak to a lot of tortured souls at the time (who had just found out they were going to be forced to migrate their projects to something else anyway due to Google's absolutely insane "we're deprecating this, we'll have a replacement for it at... some point, good luck").

The first time my team uses AngularJS professionally, we spent a month to learn the framework, then the velocity and quality were good. The client reported a funny "bug" that the loading icon didn't show, it turned out the async request was too fast that they couldn't see to loading, a fresh experience for them at the time.
> Google's absolutely insane "we're deprecating this, we'll have a replacement for it at... some point, good luck").

Angular 2 came out in 2016, without the two way binding design issues of AngularJS. Google ended support for AngularJS on Dec 31 2021, so there was 5 years of overlap between the two. They even had migration paths that allowed AngularJS and Angular 2 application code to live together from the initial release of Angular 2.

They announced that AngularJS was being rewritten in 2014 with no obvious migration path and didn't release Angular2 until 2016.

That was 2 years of "well, everything you write will be legacy"

> pretending like they invented FP

More like trying to explain to people who have only done imperative programming (and that also in JS of all languages) why a render function was necessary. The creator of React, Jordan Walke, was big into OCaml and one might even say he got some of the ideas of React through working in OCaml, so much so that he tried to bridge both by making ReasonML which is an alternative syntax for OCaml which has JSX and React bindings.

Yeah, there's a lot of people who have either forgotten or never knew that the context React came into was a world full of JQuery and AngularJS two-way bindings. I started my internet touching career having to work on that stuff, and boy, so much of it was a nightmare that just got endless workarounds heaped on top for basic performance issues, let alone other complications.
> More like trying to explain to people who have only done imperative programming (and that also in JS of all languages) why a render function was necessary.

It doesn't seem all that different from doing your rendering in the WM_PAINT handler, which was already how things were done in the ancient Win32 API (although it's possible [0] to draw outside WM_PAINT).

[0] https://learn.microsoft.com/en-us/windows/win32/gdi/drawing-...

As a web developer in 2014 when I first heard about react, I had never heard about WM_PAINT as I was not a Win32 developer.
The web root is a document platform. Every major GUI library have a “paint” or “draw” function you have to overload for custom widgets. And there is always mostly two kind of widgets: actual visible components and others that are responsible for layouts.
Yes, similar to game engines too, the philosophy of throw away everything while caching what you persistently need and rebuilding the world.
The first react implementation was done in OCaml, it was ported to JS later.
Yes although technically the first implementation of the idea was XHP, ie React semantics in PHP since Facebook used that a lot.
I don't think React pretended like they've invented FP, and I've always heard them be pretty open about FRP work existing in the past and them leaning on it.
There really isn't anything in react that is inherently "bloated", most companies were indeed using it wrong, or at least in a naive way. Over-reliance on useEffects, re-render issues, non-memoized components etc. When used correctly, react 18 provides really fast web apps on whatever scale (small one pager app to massive enterprise apps).
> most companies were indeed using it wrong

If everyone is using react wrong, react has a design flaw. Other frameworks aren't slow by default.

> If everyone is using react wrong, react has a design flaw.

You're asserting that everyone is using it wrong. It's your personal opinion, and a baseless one at that which is based on a personal belief that everyone around you is incompetent and incapable of critical reasoning. It's silly posturing.

In the meantime, React is by far the most popular web framework in production. Some surveys list React with a market share of between 60-75% of all web frontend projects. It's so popular that it even leaked into GUI programming with native GUI toolkits.

It's rather obvious that assertions such as yours are detached from reality. Naturally the dominant framework will also dominate the number of newbies taking their first steps as well as drive-bys. It's also natural that the dominant framework will be targeted by the "aktually" crowd, invested in contrarian self-promotioj comments instead of doing anything constructive.

But to assume everyone is incapable of using something... That takes a lot of self delusion.

(comment deleted)
> based on a personal belief that everyone around you is incompetent and incapable of critical reasoning.

This is all news to me. I don’t think any of that. Do you make a habit of writing fanfic about other people? You also seem upset that I used word “everyone”. I thought my exaggeration was obvious. How embarrassing for us both.

If you want to make any technical arguments in support of react, I’m all ears. The only argument I can find in your rant about my character is that react is popular right now. But that doesn’t mean react can’t be improved upon. Jquery was once that popular. Then react displaced it, by being better. Soon react will be displaced in turn, by a library which addresses react’s flaws. I can’t wait.

> This is all news to me. I don’t think any of that. Do you make a habit of writing fanfic about other people?

Pointing out the absurdity of someone like you throwing blanket accusations of incompetence is something that's very specific and verifiable. If you have strong feelings about making broad accusations about whole communities, you should pause and pay attention to what you are saying.

> If you want to make any technical arguments in support of react, I’m all ears.

Would you listen? I mean, the main issue with your post is the way you throw absurd blanket statements about a technology, on how either everyone using it is incompetent or the framework is somehow broken.

I mean, does it even dawn upon you that maybe perhaps throughout the past decade there might be people using the dominant framework well, and happen to know what they are doing?

It seems not, by the way you opt to disregard it and tell yourself no, everyone is either incompetent or the tool is broken.

Do you understand the absurdity of this sort of claim? Because it isn't even about React, but the way you feel it's reasonable to throw such blanket accusations.

> But that doesn’t mean react can’t be improved upon.

But that's not the claim you made, was it? Do you need me to quote you back at you?

Is this tiny comment what you’re mad about?

> If everyone is using react wrong, react has a design flaw. Other frameworks aren't slow by default.

The claim that react is frequently misused was from the parent comment, not me. If you read it, you’ll see I’m explicitly not blaming react devs. I’m blaming react. Vdom diffing makes websites slow by default. And it is totally unnecessary.

Most of your comment is a big ad hominem attack. To answer your explicit question, yes I would find a technical argument much more convincing than a list of made up character flaws. Especially from a stranger, based on a two sentence comment. What a waste of time.

For what it’s worth, I don’t go around thinking everyone around me is an idiot. But your comment does get me thinking.

"You're asserting that everyone is using it wrong. It's your personal opinion, and a baseless one at that"

Their comment does not assert that. They are responding to someone else's assertion, and turning it around to make a completely different point. It's a common form of argument - "if you're saying that the problem is everyone's getting it wrong, then I disagree and the problem must be something else."

Basically the exact same point that you are using to launch a stream of insults!

Saying that it is "silly", "detached from reality" and "delusional" for making assumptions about folk is the most incredible self-own.

React is very similar to PHP in this regard. PHP has (had?) several major design flaws, and yet it became the default for people with less experience.

I don't think that React is as problematic as PHP ever was, and also frameworks like Laravel have improved the PHP experience tremendously, so there is now a way for less experienced people to use it.

IMO: the problem here is pretending that everyone has an innate right to use React right when it's clearly a library that works better when people have a bit more experience than the average web dev.

We as an industry tell people "don't do your own crypto, it's hard to get it right". We don't blame crypto for being hard, or demand new frameworks. Same for things like assembly, C++, Rust, formal proofs, writing an OS, operating BGP infrastructure, etc.

But with React it has to be "kid gloves on", otherwise it's shit?

This is perhaps a bigger problem in our industry: lack of experience is not seem as an individual problem, and we blame-shift, blame marketing, blame Facebook, Dan Abramov, trends...

Perhaps we should be saying "React is not for beginners", same as "don't do crypto".

Web dev is special. The industry has spent the last 20 years sacrificing almost everything to make building web sites more beginner friendly. There is an expectation that the "full-stack" (everything between node and react) should be effortless, that is absent from other fields. "one click to deploy" in not a thing in crypto, in embedded or in kernel dev, for instance; whereas it's expected that a junior web dev is productive from day one. That's just normal industrialization, specializing jobs and then making them simpler, starting where the numbers are larger.

Ironically, piling up simplistic technologies have created quite complex houses of cards in places. HTTP itself being the most obvious example of a tech meant to be simple and quick to grasp that morphed into a super complex, ineficient and insecure gremlin of which nobody who is not a specialist (or an AI) has a full picture anymore.

Nobody I ever worked with ever said anything even remotely close to that first paragraph.

"Full stack should be effortless"? What? This is definitely not coming from anyone other than two groups: random HN people with an axe to grind, or people trying to diminish the value of the profession.

Hiring for web is difficult, salaries are historically good, people complain about complexities, including yourself: "quite complex", "super complex", "nobody has a full picture".

Nevertheless: React proves that it's not true. There are complexities in there and kicking and screaming saying "it was supposed to be easy!!!" won't change the situation.

"It should be simple" yeah Crypto should be simple as well, so there are no bugs. But it's not.

Maybe learn to value other people's jobs.

> Nobody I ever worked with ever said anything even remotely close to that first paragraph.

No, they’re correct. Many people in the web dev community spent a couple of decades there obsessed with being beginner friendly. For example, “Anyone can learn to code”. We pushed back against anything perceived as gate keeping. There was general assembly and other coding bootcamps, to teach beginners web dev. And a million beginner videos. Web dev events at the time were full of beginners. I remember a show of hands once at SydJS. 70% of people in the room had been programming for a year or less. I stopped going, because speakers started catering to the audience.

Other areas of programming aren’t like this. Nobody runs 12 week coding bootcamps to teach complete beginners to build operating systems. It’s accepted you shouldn’t roll your own crypto. And we tell beginners to use Postgres, not roll their own database.

I’m not saying it’s a good or a bad thing. But it was definitely a thing.

Bootcamps teachers, company owners, HN posters and anyone with an interest in keeping the salary low will have this opinion for sure.

This still doesn't mean the web programming owes anything to those people.

Did anyone say they do?
Yes. Whoever said React must be foolproof.
(comment deleted)
My management didn’t say it explicitly, but did so through their actions.

A self-service portal was created internally. Every infrastructure team was expected to make services available via this new portal. Timelines were tight, primary jobs were still expected to be done, and the chief architect on the project said creating the API only takes 10 minutes.

To onboard and use this self-service portal, these teams (many of which who didn’t have a single developer, but rather sys admins) were expected to leverage Flask, React, an internal component library (3 conflicting ones with poor documentation which tweaked inputs from 3rd party components and required spelunking into the code to find how to use them), and very strict rules around the Flask API… all in managed repos that required approvals for PRs from a non-responsive team.

This was supposed to be a little week-long side project for a bunch of non-developers, with no training, insufficient documentation, and little support by the person who built the portal.

Needless to say, the project is now dead, but it took about 3 years. During those 3 years, the ideas that “full-stack should be effortless” was the prevailing view, and that anyone off the street should be able to effortlessly plug into the framework that was created.

>not a thing in crypto

People are deploying meme coins to blockchains with a single X post to a bot. The pump.fun era made it really easy for anyone to launch a meme coin.

I think the GP comment was talking about cryptography, not cryptocurrencies.
What does one click to deploy mean for cryptography?
It’s “not a thing”:

> "one click to deploy" in not a thing in crypto

Because deploy is not what people do with cryptography code.
Yes, that's why it's not a thing.
That's a vacuous statement. I can similarly say one click deploy is not a thing for hamburgers either.
You could, but you would be 100% right.
Therefore useless discussion.
My point exactly.

Nobody said there's "deploy for crypto" anywhere, so asking what it means will produce no answer from anyone.

My point is you replying is useless, therefore stop, and I shall do the same.
> We don't blame crypto for being hard, or demand new frameworks

This is not true. There are innumerable cryptography libraries whose primary reason for existence was to replace or offer an alternative to a library with the same affordances but with primitives that were too easy to use incorrectly. “Maybe we should redesign this knife so it’s hard to slice a finger off” is not unique to web dev

It’s always the same argument variation when trying to defend react: “Find it complicated? Maybe you’re stupid.”

No, using a frontend framework is not as complicated as developing your own cryptography, not even close, just use anything other than react instead.

If you can't use React, then yeah: you should definitely not use React.

Experience is required, period.

you can make anything slow
If most people can’t use it properly perhaps the problem is in react itself and not most people. React is the only framework that will blame the user for its own mistakes.
React has an incredible ecosystem, it's almost synonymous with web development. The available render backends alone, namely React Native, are currently unbeaten.

As interested as I may be in the alternatives, they simply don't have this.

(comment deleted)
Alternatives might not need this though.
> They ran react conferences, teaching everyone who would listen about "1 way data flows" and pretending like they invented FP.

When you have to resort to outright lying about something it's usually a good sign your argument is flawed.

I haven’t found a front end library I like more than React except maybe Astro.

I didn’t really like Svelte and I am pretty opposed to htmx. It is certainly better than Angular and Vue, though Vue 3 is tolerable. Maybe there are more popular options nowadays but tbh I am not really looking to move from React. I have zero complaints other than maybe the push towards server rendering and partnering with Next.js

React is simple and I like that it feels a bit like FP. I love that I can write just about my entire application in TypeScript with all of the benefits that incurs. It requires some knowledge/discipline e.g. around useEffect.

If you care to use native browser APIs and features you can have lightweight, performant applications that behave well in the browser.

Most devs don’t do this, even with vibe coding. It’s a very easy way to filter for those who care about what they are building.

I have to step in here to say that at least documentation wise, this is revisionist history.

The original react documentation is fine, but focused almost entirely on class components. What was there on hooks was either outdated or outright harmful.

It's not until 2023, 4 years after react hooks launched, that the new react docs which focused on them were released.

Yes, the original documentation is what I’m talking about. That documentation was not outdated when it was written. It was excellent compared to the standard at the time. The react doc site raised the bar for what we expect from web framework documentation.

Hooks came much later, long after react was already popular.

I have stubbornly avoided React. When native WebComponents became a thing, I figured I'd try them out on a small internal site I maintain. It was very slow. In an effort to reduce a bit of duplicate code, my site when from loading instantly to having a noticeable load time. Having to employ tricks to try and optimize and speed up the most basic implementation of a built-in feature seemed like the wrong move, so I ditched them all together and reverted back to my old structure.
Not to piss on your experience, I use WebComponents for almost everything and they have a lot of issues (mostly they're not really integrated into a coherent model with the remaining things that always exist in their presence, the browser, DOM, lifecycles, requests, etc) but being slow can only be an issue of your implementation to be honest, it's an imperative model for the most part - in fact the reason why I've started using them was because it was much easier to make things fast easily - there's no way updating/replacing dom elements surgically is faster with any other framework.
Only if you mean React before they went crazy with hooks and "use whatever" magic strings.

I put up with it, because plenty SaaS products favour Next.js and React as their only extension SDK.

I would never pick it up freely, all side projects with Web are VanilaJS, coupled with what is available on Java, .NET and PHP.

What do you not like about WebComponents?

Say we want to make an icon that when clicked shows how often it was clicked. The webcomponent code seens quite sane to me:

   class HelloIcon extends HTMLElement {
      connectedCallback() {
        this.clickCount = 0;

        this.innerHTML = `
          <button class="icon">:)</button>
          <dialog>
            <p>Hello, I was clicked 0 times</p>
            <button class="close">Close</button>
          </dialog>
        `;

        const icon = this.querySelector('.icon');
        const dialog = this.querySelector('dialog');
        const closeBtn = this.querySelector('.close');
        const dialogText = this.querySelector('p');

        icon.addEventListener('click', () => {
          this.clickCount++;
          dialogText.textContent = `Hello, I was clicked ${this.clickCount} times`;
          dialog.showModal();
        });

        closeBtn.addEventListener('click', () => dialog.close());
      }
    }
Try it here:

https://plnkr.co/edit/0XUOLyM52xfFiIBu?open=index.html&previ...

That's the best case scenario and already looks like crap. If that looks sane to you, I don't know what to say.

Make it have an initial count via attributes, sync it with the DOM so if the attribute changes the count resets, and make the JS property always match the attribute (and vice-versa) so it behaves sanely. You're in for a world of pain even for something as simple as this.

I've worked extensively with Web Components. They suck.

Web components are intentionally low-level, they’re not really meant to be used directly. You should see them more as performant, interoperable building blocks. Have you tried lit?
This circles back to the OP's point: they're not appropriate to use directly, so we layer a framework on top of them (Lit), and now we're just using another framework with one small piece swapped out.

Except for the hyphens, I don't feel any closer to the platform when I use Lit.

You can inspect a Lit component directly in Chrome, it’s just a custom element. No need for a browser dev extension. You can use this custom element from React or any other JS framework. You can also use this custom element in a server-rendered template, no need for any custom SSR setup. Feel close to the platform yet?
For starters, that it introduces weird special cases to DOM parsing and structure, thereby breaking .isEqualNode whenever <template> elements are present.
Why are your component styles global not encapsulated within the component?
I don't know if that's idiomatic webcomponent or not but that looks unmaintainable, even for such a minimal component, imagine once it grows. It's not separating presentation from state and logic. querySelector need to match classes and elements in the markdown. Mutating textContent is going to run out of sync as soon as you have more than one event source doing the same. Those are all problems that React solve by separating state and only rendering in one path.
Well for one thing, I don't find that to be particularly succinct or nice example. There's a lot going on there:

- HTML in a string. No syntax checks. If you template it, you have to escape manually or you could create trivial XSS vulnerabilities. Your editor will probably not syntax highlight it, making it harder to tell when you break it.

- Manually formatted update logic that is redundant with the template. Not so bad here, but try formulating a practical large component.

- Completely ad-hoc state management, no reconciliation. Again, fine for Hello World, not fine after that.

Using raw WebComponents, your application has to care about all of this on its own and more. You can use templates and slots (which you should) but that makes this even messier IMO and brings back the split that React became famous for getting rid of. We left manual DOM reconciliation, ad-hoc data flow and non-reactive components that manually call a render routine at arbitrary points for a reason: it sucked. It made for buggier, harder to maintain code. It can be done, but usually any decent app will wind up encapsulating patterns into utilities that get reused. And... That's precisely why we want a good library. That's what I want, a library that packages up good reusable patterns for constructing UIs effectively.

And that's exactly my point, which is WebComponents or not, the solution is still basically the same, use libraries. Which begs the question: if I have to use Lit, what is the point of "using the platform"? What is WebComponents doing for me here that React wouldn't be? And in my case, I struggle to see it.

Interoperability? The old way of embedding external components works quite fine. Switching APIs where you pass a DOM node for something to mount into and get back an object with an API to one where you instantiate a component and communicate via properties and events feels like a strictly lateral move. I can't think of a condition where this would be particularly more convenient, but I can think of some where it is actually less. Next.

Isolation? Yes, WebComponents does add tools to provide better isolation between components. For some use cases this is a genuinely useful feature, although it also isn't without tradeoffs (I mean, the flexibility of having things be not isolated comes in clutch sometimes, it's hard to argue this.) But I use React primarily to construct components in an application, where I find this property more undesirable than desirable.

The one thing I thought could be cool with WebComponents is if you could build them in pure HTML when you only needed basic templating, but no: the design they went with always requires subclassing in JS AFAIK.

I could go on and get more specific, but I feel like people will pick everything I just said apart quite enough. I hope I'm at least able to make the case that:

- I do in fact, get the general gist of WebComponents.

- I still don't like it despite that.

> Isolation? Yes, WebComponents does add tools to provide better isolation between components. For some use cases this is a genuinely useful feature, although it also isn't without tradeoffs

I hate the guts of every site that uses those. Shadow DOM makes the site hard to operate and fix programmatically from user end.

I mean, these days I can just throw an LLM at it so I don't care as much, but sometimes I want to still do things hands-on. Not to mention, Shadow DOM is often a difference between "simple userstyle/userscript that is allowed at work by security extensions" vs "requiring things that are banned on corporate-managed browser".

> If you interpolate it, you have to escape manually

Well, for some definition of "manually".

If you have untrusted variables to interpolate, you can do

    this.innerHTML = html`Hello ${name}!`
Where html is a function that escapes the variables.

The arguments brought forward against web components all seem to fall under "But it does not contain every functionality you want to use out of the box". Personally, I don't think browsers should provide more and more functionality, but rather a good base to build upon.

The reason react sites are bloated is because there are a lot of things that are easy to do once you have better DX, there is nothing stopping you from making completely static sites with no js (solid-js 2.0 has a whole "htmx-like" mode that lets you have good interactivity even with js disabled).

WebComponents are useful for cases where you want something slightly more integrated than an iframe or want to make a library of small widgets

If that is what sane web component code looks like, I never want to use it ever.
This is a very simple component, and its already a mess.

Something with more HTML and javascript is going to be a nightmare.

Then theres the problem of sharing state, the world is far more complicated than something simple in isolation.

(preface by saying I use webcomponents regularly, I can show you a game that's currently online where they're used extensively)

I don't really understand why people are complaining that this is unmaintainable on the replies to this snippet but there's plenty of things with webcomponents in general that could be better done on the browser side.

For one the innerHTML (or some new method) should be able to reference a `template` directly. If you want to use templates you need to do:

``` const template = document.getElementById("templates-materialization-base").content;

this.appendChild(template.cloneNode(true)); ```

And if you want to use templates then you need to render the templates in a part of the dom that is parsed before this JS is run - there's no way of specifying dependencies for this kind of things - which is a short-coming of the platform as a whole.

One the same topic there's no way of providing an url for retrieval of a fragment that contains templates and have it parsed directly and available to subsequent JS if you could do:

`<HTML-FRAGMENT href="/my-endpoint/returns-templates.html" required="true" id="MAIN_FRAGMENTS">` or doing `fetch("/my-endpoint/returns-templates.html", {DOCUMENT_ID="MAIN_FRAGMENTS")` would parse the result and make it available to the browser engine then you could have on subsequent JS:

`<script requires="MAIN_FRAGMENTS" wait="GLOBAL_LOADING_INDICATOR`>....</script>` or in a file/module `requires DOCUMENT_ID: MAIN_FRAGMENTS` and the file/script execution would block until that would be available, just that would go a long way. You could specify fragments (the component DOM templates to be used) that are needed for the webpage to work at all, fragments that would only show loading for their own content, etc (you could style the TAG with a pseudo-state indicator, so if it had a wait not resolved yet, CSS could target it with `MY-TAG:state(waiting)`).

Another issue is `attributeChangedCallback` - this doesn't take into account how most of the times one can/will update the attributes of an element, so it fires once for each change, even if you made X changes in one swoop, making it so that you have to have to make a more complex "update_render" function to work around that, or lots of small functions that are composable (ideally, but not practical or wanted in many cases where the whole thing is to be treated as a single update) or create a `batched_attributeChangedCallback` that you implement yourself as part of a class mixin and then extend the HTMLElement class on declaration and use that, because most of the times you want to re-do/update the whole component and when you have multiple properties (equivalent to react props and similar in other frameworks) and multiple components this can result in expensive updates to the page that the user feels as sluggish on their end. Something like:

`batched_attributeChangedCallback(attributes, old_values, new_values, batch_timer_window: 200, batch_timer_fn: true)` where the default for the batch window is 200ms, but can be provided a `fn` that does the evaluation to. So even if the updates are done independently but under the timer window they're batched instead of run 1 by 1 (or immediately if the `fn` returns true, defaulting to true when it's independent 1 by 1 updates).

I usually have a function `_set_handlers(boolean)` that is used on connected and disconnected callback but this is just plain js organisation:

``` _set_handlers(toggle) { let act = toggle ? "addEventListener" : "removeEventListener";

  window[act]("some-window-event", this._maybe_ready);
  this[act]("some-component-event", this._some_fun.bind(this));
} ```

And the connectedCallback just calls `this._set_handlers(true)` and disconnected `this._set_hanlders(false)`.

I use them, you can use them...

> ``` const template = document.getElementById("templates-materialization-base").content;

this.appendChild(template.cloneNode(true)); ```

It was pointed out to me that `this.appendChild(document.importNode(template))` is faster due to "adoption" (`importNode` clones and adopts the nodes for the current document at the same time/single tree walk, saving appendChild from having to do a separate adoption pass/tree walk; template.content exists in a fake separate document so the nodes need to be "adopted" by the current document).

Which is a point in favor of the current complexity of the JS API for working with templates. I agree that "HTML Modules" would be nice to have and more declarative template usage that doesn't require the Shadow DOM would be lovely. Both are still proposed standards going through various debate cycles.

> making it so that you have to have to make a more complex "update_render" function to work around that

One potential simplifying answer when trying to deal with batched updates to attributes is a simple "dirty flag" and requestAnimationFrame callback as your "update_render". Most things changing more than one attribute at a time are likely going to do it all between animation frames and even if they can't, rAF provides other throttling that prioritizes user interaction.

There's still complexity in that approach, but it is isn't as complex as trying to build a throttling timer.

> I usually have a function `_set_handlers(boolean)` that is used on connected and disconnected callback but this is just plain js organisation:

It looks like you could replace some or most of your `_set_handlers` function by implementing `handleEvent(e)` for the Web Component. It's an auto-registered/unregistered handler at the component level of the event bubble.

Thanks for the `handleEvent` tip, that's useful for component wide events, but it creates some problems if you need to prevent the event at the input level, because some (specially those related to submit) will need to pass through the form to bubble to the component level and will trigger it, and preventing it at the component level wouldn't cut it if I'm not mistaken? It also doesn't cover events on the document, but that can be worked around and perhaps even clearer to have it separated (`set_global_events(boolean)`). it's a good option to be aware of but I also like segregating them in that way since it allows me to turn on/off from other parts of the component outside the lifecycle calls (or even from a parent component) - sometimes useful too.

You would also need to switch inside the handle event to deal with the different types plus the different targets that might be bound to those events inside the component so I think that for anything with a modicum of complexity it doesn't cut it, unless I'm misunderstanding how to apply them in those cases (pattern matching with multiple function heads would definitively make it read like a declarative model but is not really serviceable in JS even if you syntactic sugar it, you wouldn't be able to describe `target` html elements probably - like:

`handleEvent({type: "click", target: {TAG: "input", id: "some-id", type: "input"}) { ... }`

and then another

`handleEvent({type: "click", target: {TAG: "button", ...}) { ... }`

, etc).

The importNode I think there was some issues with some properties not being copied outside of clone? I can't recall why I defaulted to `cloneNode`, could also be I just missed the `importNode` altogether or misread it at the time, but it has worked fine since then so I didn't look for ways to do that better.

Regarding batching, I basically have been using the same class extension since I've started working with webcomponents and it works, it uses a timestamp to control if we're inside the batch window for the inner working and then the "apply/build" part of each component has to compare those and decide - this is the part I would rather not have to code and have it handled natively (some events might actually run a single pointed update while others run the "full" apply/build function). It's nonetheless a bit more wiring and someone that never seen it might have the same reaction as some people here, even though they're fine in importing 50 libs, or 20 lines of useMemo with useState and useWhatever but heavens forbid they might need to read a 50loc class module. At some point many components need to ditch the `attribute` change handles as parsing the attributes into json/objects can get expensive, and you need to start doing parent->child direct data transmission and this is the only real bottleneck I've experienced when using attributes and requires an overhaul to how data is passed into the children (either from parent orchestration from top level attribute parsing that is fairly less taxing when done once only, but at a certain point can still stall the main loop just the same, at which point you need to parent-level requests, websockets, SSR that then you can pass directly to the child child_component._set_whatever_data_function(data) or setting the prop directly if it's workable in the particular case).

The thing with being able to load html fragments (or, even if whole html docs would be what we settle into) and having it be available would be that you could separate them into cacheable requests - so if you have `/essential-templates.html` , `/signed-in-templates.html`, `/special-page-templates.html` they could be cached, which means they would only need to be refetched if they changed or TTL expired. But with no way of declaring dependencies it can (will) also introduce bugs - if there were we could probably do some cool (as in use...

[delayed]
Formatted so I can read it (on mobile...):

  <script>
    let count = $state(0);
    let dialog;
  </script>

  <button
    onclick={() => {
      count++;
      dialog.showModal();
    }}
  >
    :)
  </button>

  <dialog bind:this={dialog}>
    <p>
      Hello, I was clicked {count} times
    </p>
    <form method="dialog">
      <button>Close</button>
    </form>
  </dialog>
The inline onclick handler doesn't seem super readable, but the rest is fine.
I assume for most real world, non-trivial cases you'd be defining the click handler inside the scripts above.
If you do this you might as well just write JavaScript without using WebComponents. APIs like innerHTML, querySelector, addEventListener have been around for decades.
>What do you not like about WebComponents?

I think the problem is not what I don't like about WebComponents individually. The problem is that to use WebComponents, you have to use JavaScript anyway and if it does not do exactly what you wanted, then you're right there, in JS, ready to DIY the problem away.

If WebComponents were purely declarative, I would try harder to use them.

> The webcomponent code seens quite sane to me

If that's a joke, it passed over everybody's head here. I can't imagine it's serious, but it still doesn't sound like a joke to me.

WebComponents are some of the coolest APIs on the web if you ignore all the ways they fall short and make everything else harder
Isn't it missing a removeListener?
What about the web components APIs are bad, and how could they be done differently given the reality of the existing platform?
The current state of the platform has even been a blocker to standards folk when they want to add a shiny new thing, thus the absurd bloat of the specs.

For one, they can stop pretending that JS and the DOM are two completely separate entities, and lock the two working groups in a basement until they figure out a sane way to do reactivity, natively, that actually works.

So any specifics on web components? What part is actually bad and how could it be better in a way that actually works?
Nitpicking specifics misses the elephant in the room:

> figure out a sane way to do reactivity, natively, that actually works.

(100-epsilon)% of developers write websites in a reactive framework, and the reason we have so many of them is because the platform doesn't provide a sane way to do it, so we keep trying again and again with different hacks on top - virtual DOM, proxies, literal JS to JS compilers, whatever some crazy guy happened to come up with last weekend.

That's the problem developers have, and WebComponents don't solve it. They can't. Nothing you do in the DOM can solve it, you need support from the JS side. Thus, lock the two working groups in a basement until they start talking to each other.

All developers want to be able to do is write this:

  JS:
  let my_stuff = [1,2,3];

  HTML (made up template syntax, pick your favorite one)
  <ul><li><$for thing in my_stuff><li>$thing</li></$for>

  JS again
  my_stuff.push(4, 5);
  my_stuff.reverse(); // the user now sees 5 4 3 2 1
Any major update to the Web standards that doesn't help address this can be dismissed outright, as the community did with WebComponents.
I've written something close to this called Solarite... that uses web components. There's no build step and no signals, but unlike your example, each instance is bundled together in a class, and you need to manually call render() when it's time to redraw. But I actually prefer having that control.

https://eric-frost.github.io/solarite/

Reactivity would be an addition to web components, and you can layer that on in userland. Plus, there are proposals for exactly that.

But if the web components APIs suck, what sucks about them now?

I - like the vast majority of web developers - do not care in the slightest about WebComponents, as they solve problems I don't have, create new ones that I do have, and don't solve the problems that I already have.

I can't spell it out more clearly than I already did, I believe you're being obtuse on purpose.

It would be more clear if there were any concrete critique of the web components APIs.
Components without ShadowDOM not having a slot is the biggest known issue.
How would you solve that? To this day I've never seen a workable proposal.

Slots need to have a host element to select slotted nodes from. ShadowRoot provides that host. Everyone who I've seen say that it's easy comes up with an ambiguous system that doesn't work in many cases and could never be standardized.

Which is a common problem with most "web components suck" takes - they have no sympathy for standards developers or the difficulty of the problem and somehow assume the spec people are dumb or evil, and they don't do the work to show how something could realistically be better.

> How would you solve that? To this day I've never seen a workable proposal.

Stencil.js[0] has a working "proposal" or workaround. Not sure if it is good or bad but at least it seems to work. When you ask users of an API how it could be better they should not be responsible for the implementation. If it can't be done so it is better to not do it in place of having a half working solution that most people decide to not use because it does not work for their use cases.

> they have no sympathy for standards developers or the difficulty of the problem

The problem with the browsers API is a lack of an understanding on how to design good ergonomic APIs for the end user. All the standards developers I talked think shadowDOM is great and people not using it are holding it wrong.

0. https://stenciljs.com/docs/templating-jsx#slots

Stencil's is _not_ a workable platform solution. Stencil is emulating something close to slots _above_ the DOM. Stencil knows the host tree form Stencil's own component definitions, then it flattens before it gets to the DOM. This is basically just what React and every other framework does, just copying the browsers terminology. It's not compatible with anything but Stencil.

In the real DOM you need to know which element from project _from_. The <slot> itself is only half the connection. In a light-DOM only document full of <slot>s you won't know which elements to project where.

> The problem with the browsers API is a lack of an understanding on how to design good ergonomic APIs for the end user.

This could be slightly true, but the statement also misunderstands the role and priorities of standards. When adding new capabilities to first priority is to make something possible at all, and coherent with the rest of the platform. Making a sugary high-level API is often left to libraries at first, and is exactly what libraries like Lit are.

I'm not GP, but I would love to understand this issue in more detail. Do you happen to have a good link for me to read about what has been tried and why it failed?

Perhaps it's a naive solution, but I would imagine that much of that could be solved through deferring to component hierarchy and enabling a way to assign things more specifically when defining the components in the CustomElementRegistry. I recognize your username and I realize that you have spent a lot of time thinking about these problems, so I would really appreciate whatever insight you have to offer. Thanks!

> In the real DOM you need to know which element from project _from_. The <slot> itself is only half the connection. In a light-DOM only document full of <slot>s you won't know which elements to project where.

There's still a concept of "importing" a template. A host node has slots under it and requests to "import" a template from elsewhere in the document. That import process can adopt the slots then. It's "adoption" rather than "projection" and you "lose" that relation to the source document that "slots stay in the same place", but the DOM has never been static with respect to source documents.

I don't think that standards did anything wrong or incompetent, but with hindsight considering all the complexities they bring i am hot sure they have been worth it
Stencil or Lit are basically required, yeah.
It’s surprising how bad the API is. Shadow DOM makes just about everything worse. Our frontend org opted out of even using Lit, so we get the raw stupidity of the whole idea.

Style encapsulation? You get that, but not fully, and good luck finding out which parts you don’t get.

State management? Back to query selectors, which btw work worse and need workarounds when reaching into the shadows.

Slots? After coming from a modern framework, slots are a clear step backwards. In React you can pass a component as a prop but in the shadow DOM world, you have to signify it with HTML. Multiply it by several slots and you get a lot of verbosity just to match the behavior.

Yet to mention using the platform directly means losing so much work around static verifiability. No one has to talk about this anymore, but sticking religiously to the platform by strictly using addEventListener means you can’t require event handlers to exist for any of your elements. People forget this, but the browser’s default way of letting you do anything is an enormous footgun for reliability.

Learn from our frontend org’s mistakes. Run, don’t walk, away from it.

How can you say react isn't bloated it requires a full download on first website visit, web components are browser native, not saying they're better, but to say react is not bloated is an affront , there was a time where people were carefully deciding on whether or not to include jquery.
> full download

Like 50kb. Roughly the same size as Amazon website's icon sheet.

If you are referring to how SSR pages need to download the serialised page "props" and not just the html+js then good news! Solid 2.0 is about to solve this.

If you are referring to having to download react itself then you have to download the WebComponents code too.

Actually with smart use of forms and links you could make a js free react page (using forms to submit state changes) more easily than for WebComponents

WebComponents were created out of spite for react and are the composability equivalent of medieval artist drawing horses that look like they had never seen an horse
I don't understand why browser makers don't just steal the API from popular solutions like React honestly. That's "fair use" since Oracle v Google afterall.
People are using things like lit and react not because web components suck but because they want something reactive (declarative UI bound to app state).

Web components are lower-level than that -- they can be one building block for this (e.g., lit), but don't accomplish it on their own.

+1 for Lit. I use it for an inbox web component that runs in React, plain HTML and Blazor with the same bundle.

Much less boilerplate than raw custom elements.

> For one thing, I just genuinely think WebComponents are a badly designed API that is weird and hard to use (how many people are using WebComponents without at least Lit, if not something much bigger?)

I've been using Web Components entirely without Lit (and somewhat dislike Lit) both "Vanilla" and with a JSX framework that is not a Virtual DOM (not React).

I think WebComponents for me started to click when I realized that for the most part I don't need the Shadow DOM at all and can work entirely in the "Light" DOM.

The other thing that only more recently clicked for "vanilla" Web Components work was moving to implementing `handleEvent(e)` and relying on "old fashioned" event bubbling over endless `this.querySelector('#element_name').addEventListener(…)` (and `removeEventListener` if you are a good citizen and care about garbage collection) boiler plate.

The Shadow DOM makes sense if you need a more powerful `iframe`, but that's almost never what I want, because I trust CSS and trust the Cascade. So much of the Web Component API complexity is just and just for Shadow DOM. Web Components make so much more sense in the "Vanilla JS" world as soon as you realize you can YAGNI Shadow DOM and stick to the Light. I understand that for ad companies and "powerful embeds" companies really want a higher powered `iframe` and so I can't blame Shadow DOM for existing, but I can blame Shadow DOM for making Web Components look like frightening things that "need" Lit rather than simple things that Lit pretends are more complicated than they are because it also assumes you want to start from Shadow DOM by default rather than Light DOM by default.

(You don't get some of the automagic of the `template` tag if you eschew Shadow DOM, which is silly and "Light DOM template standards are still on the roadmap" but the `template` tag is still useful in Light DOM work, and ironically Lit doesn't make good use of the `template` tag anyway so even most Shadow DOM users are not using `template` much yet.)

Similarly, a lot of the "I need a framework like Lit" comes from event handling and it feels like a full circle of the jQuery days with lots of querySelector/querySelectorAll and addEventHandler/removeEventHandler imperative shuffles in connectedCallback and disconnectedCallback, but one of the things that created the situation that was jQuery event handler hell was people not learning and/or distrusting the event bubbling system and one of the performance tools (that even React uses under the hood) in the jQuery world became moving event handlers up the bubble chain and being smarter about fewer handlers (even as the jQuery "state of the art" never strayed very far from lots of very specific handlers). (In React's case this is why in the debugger you often see classes called SyntheticEvent and friends because React often subscribes at a higher bubble level and then creates synthetic events to make it look like you are creating event handlers lower in the DOM.) In the WebComponents world you can implement the `handleEvent(e)` in your (Light DOM) Web Component, get addEventHandler/removeEventHandler "for free" from the browser, rid yourself of a lot of query selectors, and take (performance) advantage of the event bubbling.

For the same reason that most jQuery era scripts still used very explicit query selection and on/off handlers and React uses synthetics to pretend to do low level event handling with bubbled event handlers there's a developer experience issue in building combined event bubble handlers versus "localized" event handlers to deal with, and that may still often lend to wanting a framework to support writing event callbacks as "localized" event handlers, but Lit isn't doing anything particularly interesting there either (it takes an approach somewhat like Angular, preferring localized ha...

Wanting scoped styles without shadow DOM was one of several reasons I wrote my own library, Solarite: https://eric-frost.github.io/solarite/
Scoped styles hasn't been an issue for me, but I understand why a lot of people want them.

My own library wasn't designed with Web Components in mind, but I keep finding it useful for them and some of my "v2" project is expanding what is possible/easy with them. https://worldmaker.net/butterfloat/

Because the platform is too hard. The average person does not want to spend time figuring out how to get stuff to work. All the browser documentation is 1000 times nerdier than the average person wants. They want all this low level stuff abstracted away from them.
Because the platform sucks. I want a rounded button with a certain radius and a certain font, that feels squishy and satisfying when you press it, especially on mobile.
What do you mean by “squishy and satisfying”? Otherwise it’s easy.
As far as I know there are still some things "the platform" actually won't deliver; for instance I'm fairly certain there's no searchable combobox that's fully accessible. One ~must leave the platform to give users the experience the expect.

That means "the platform" itself is actually teaching people to work "off platform" and arguably will always have gaps as functionality and expectations evolve.

Admittedly, the habit really ought to be 'I need to make a combobox -> does the platform have what I need? -> Research, evaluate, test -> Otherwise, make it' but I don't begrudge people for skipping the middle steps.

Especially because the last step is less "make it" and more like "npm add it".

The browser has "ready-made components". React (et al) also has "ready-made components". React's selection is a thousand times larger. React also allows you to make your own. The browser doesn't [1].

Who can blame developers for skipping the inconvenient half-solution and going straight to the all-encompassing ecosystem

[1]: It does, but web components are too unwieldy to compete with React

The vast majority of the patterns in the ARIA APG require bespoke JS plumbing for proper focus management, keyboard controls, and etc.
Isn’t datalist doing that? Last time I had to build a combo search box I was pleasantly surprised to learn about it
There's also no virtualized list, which has been the defacto standard for the past 20 years in every other platform.

This forces devs to use userland hacks which break accessibility and lower performance.

It's because frankly the platform has been historically shit. Web components comes to mind as someone else here has mentioned, as it's just not a good API and needs wrapping to make it usable, same as IndexedDB which the author readily admits as a creator of such tooling. It seems like the ones who determine the platform aren't actually developers day in and day out and thus don't dogfood their own products while the rest of us do, leading us to reinvent the wheel.

Here is a great comment and discussion (scroll down) by Ian Hickson who wrote the HTML5 spec on how the platform has essentially failed on its promises causing everyone to write everything in JS or even other paradigms like Flutter and other WASM or canvas based frameworks that eschew the web entirely: https://news.ycombinator.com/item?id=34612696

can the title be changed to "Why don't more developers use browser native features?"
Is it just me or does it feel like Anthropic and OpenAI (and probably others) are pumping harness engineering and the like to try and convince engineering organizations, or even entire companies, to "use the platform", and not meddle with software anymore?
I guess static HTML is easy to scrape
I must say it was worth reading , thanks for sharing your insights !!
There’s only one “the platform” but there were tons of competing libraries to do things like css, components, etc. The competitive landscape just produced better results. For me, Tailwind is nicer to use than regular CSS, and React is nicer to use than web components.
> The argument is simple: why build something yourself, in JavaScript, when the browser can do it for you?

And when it becomes real, you've got yourself an argument

From other comments that are focused on the code part of the subject, I think there are 2 big forgotten points here: time and hype.

Time: since platforms are big machines, their timeline and backlog is huge, and the self-taught geek does not consider (care) that. So when there is an obvious little hiccup somewhere, they create a bug report that asks for details, proof, reproduceability,... and finally get pushed back to eons because there are more pressing concerns to attend to at the platform level. Meanwhile, it takes about 1h (without AI) to code a workaround and feel like a hero because "I've fixed something that took them 3 years to triage".

Hype: yes documentation and code quality and all matter, but it matters even more when it comes from Google or Meta! We all feel little compared to giants and when they open their internal secret tooling framework (with big marketing budget) then we all feel like there is a secret to grasp and a key success factor to wield. So it is not so much whether a npm library some nobody created exists, but whether the main contributor works at a big brand name. It does not prevent smaller anonymous projects from emerging but lets face it, it is much more appealing when it is how Cloudflare handles it at 1e20 scale (because we all feel we face the same challenges of course).

When a technology becomes popular enough, it develops a community that solidifies that choice: conferences, books, extensions, a generation of engineers that see things in terms of React.

A technology needs to be a lot better to overcome that aspect.

Sometimes I visit a subreddit for a tech and see them all discussing strategies/techniques that are ultimately workarounds for what an alternative technology has fundamentally solved, but... the original tech has an army of volunteers able to help newbies workaround it, which is often an easier onboard experience than the alternative tech that just works, but doesn't have any advocating solutions/blog posts because there are no blog posts to be written.

Counterpoint: the problem was solved by an alternative, but was it solved without any tradeoffs? If the solution comes with no real tradeoffs, then that begs the question why React wouldn't simply adopt the solution... And I think this is not a theoretical nitpick, either: Angular actually has, to my knowledge, basically done this more than once. And React certainly doesn't seem afraid to make big or breaking changes, from fibers to suspense to hooks to context, so I don't think it is resistance to change at play here.

I think when you consider that the solutions sometimes may come with tradeoffs that cause problems that people like less than simply working around the first problem, it makes a lot more sense.

I don't think conferences, hype, corporate backing explain the continued success of React; they help but it's just not the full story. I don't think they explain the continued success of anything else, either; I find this to be a shallow and lazy dismissal in most cases. It's easy enough to find counter examples where none of these things, not conferences, hype, corporate backing, or whatever else you could think of, were enough to make something work. While these things definitely help keep something relevant, they can't do it alone.

In fact, in attempting to rationalize the success of React without acknowledging its strengths, I believe people have fundamentally reversed cause and effect. I think a lot of the continued success of React comes from people continuing to choose its set of tradeoffs over others even when they could tolerate risk. I think that conferences continue to be organized and books continue to be written because of its continued success.

The tech community on the Internet has largely matured enough to acknowledge why PHP was and is successful; yes, there are many objective issues with it even today, but it also has many strengths beyond just having existed for a long time, too. Do I think you should choose PHP for new projects, the way I might say for React? Well, no, not really, if I'm being honest. But, I think it was nice to see people grow up and acknowledge that actually, there were and are a lot of redeeming qualities to PHP, and what it did for a lot of people was pretty cool, fractals of bad design be damned. It'd be a shame to see this repeated again more for stuff like React and say, Go, just because it's not the dog in the race we wanted to see win. (And I would understand that position, because I fully understand why people like Svelte, or Rust. I just don't think there is a conspiracy, it's just that there isn't a free lunch here.)

I think we agree, though I can see why it might not have seemed that way, since I didn't draw attention that users might rightly conclude the overall tradeoff is worth it, even if another tech is sounder in some minor aspect.

React can adapt, and though Web Components might still have some claim on X, Y, Z, React still is heavily preferred because all the other things are so much more important to developers.

For what genuine gaps remain, there's lots of React users that can help others through it.

> And React certainly doesn't seem afraid to make big or breaking changes, from fibers to suspense to hooks to context, so I don't think it is resistance to change at play here.

As far as I know React hasn't had any such breaking changes. Those were all added on top without removing anything. Class components without hooks still work fine, for example.

As a very long time React user, React.createClass is certainly gone. So are some old versions of the context API. Although it never broke any of the guaranteed behavior, Fibers broke a lot of behaviors that were not guaranteed. Upgrading the major React version in any very large application is likely to cause at least some issue to shake out.

I think the more correct thing to say, at least in my opinion, is that React never breaks functionality without good reason. If you are following the React best practices and not relying on unintentional implementation details, using hooks/lifecycles/APIs correctly, your application will not break for a very long time.

If there was a sufficiently good innovation that was a pure win with no downsides, I believe the React devs would do their best to integrate it in a minimally disruptive way... But just like the adoption of ES classes, I do expect that eventually they will drop support for "the old way" when the time comes.

Some developers are locked in to using some in house UI solution that is slow to implement any new features from evergreen browsers and even is still shipping hacks for IE11, although it was depreceted company wide years ago.
People will just use the best tool for the job, putting aside some time it takes for practices to propagate.

Native date pickers suck, are ugly, and have no customizability, and look inconsistent between user agents. They don’t even really conform to the OS either (other than iOS). Everyone uses JS. Chrome’s native date picker shipped with a monospaced input font, for crying out loud.

Position sticky is amazing and the behavior is better than what JS can give you. A lot of people use it. Not much UI to make consistent between user agents.

Make the platform actually good and consistent and people will use it. Native APIs are always the better choice if they accomplish your need.

This article misses the most crucial point.

Developers don't "use the platform" because all the building blocks for any component you can think of are already there. When "the platform" adds yet another set of not particularly pretty and badly configurable components, why would we use them? When there's tons of mature, deeply thought out, battle tested, cleanly abstracted components out there - especially when _those_ components are made of divs and layouting and CSS and are therefore malleable to the pixel instead of being made of magic browser pixie dust?

Seems from the article that this is more "why don't more REACT developers use the platform"?

I think it is largely because IMHO React is very much an "overlay" on top of (and inspire of) normal web standards, leading to whole swathes of people who have basically only ever been "react developers" not generalist frontend engineers. They find the DOM APIs "icky" because it takes them out of the React mindset etc.

Tldr, React and NPM are a pox on the world of frontend development and especially the JavaScript ecosystem. It's given JavaScript such a bad name.

React to some degree made immediate mode UI possible in the browser, which is part of why it is this successful. If the browser gave the option to do ui = f(state) natively, you wouldn't need React.
I think the question at this point is not why React was adopted, but why it still dominates despite overriding the platform in many ways, with all the downsides that entails.

IMO did not React necessarily originate a style of programming but was undeniably successful in packaging and documenting it.