Apologies to Chesty Puller for appropriating his quote, “Pain is weakness leaving the body.”
It’s 2024, and you are about to start a new project. Do you reach for React, a framework you know and love or do you look at one of the other hot new frameworks like Astro, Enhance, 11ty, SvelteKit or gasp, plain vanilla Web Components?
In this post, I will enumerate why I no longer use React and haven’t for the past two years after 7 years of thrashing about with the library.
Quick note: I started writing this post before taking off for the holidays. Well, there must have been something in the zeitgeist, as we’ve seen a spate of articles where developers are voicing their displeasure with React.
- Increasingly miffed about the state of React releases by Tom MacWright
- Kind of annoyed at React by Cassidy Williams
- React, where are you going? By Matteo Frana
- The Decline of React by Chris Ferdinandi
- Concatenating text by Johan Halse
It’s not that React has been immune to criticism, as Zach Leatherman has detailed in his post A Historical Reference of React Criticism, but it sure seems like we’ve reached a tipping point.
The Shiny Object Syndrome
React has used the shiny object syndrome to its advantage.
Shiny object syndrome is the situation where people focus undue attention on an idea that is new and trendy, yet drop it in its entirety as soon as something new can take its place.
So, how is React like the shiny object syndrome? Obviously, there was a lot of hype around React when it was originally released by Meta nee Facebook, which had developers flocking to the library.
Whether on purpose or not, React took advantage of this situation by continuously delivering or promising to deliver changes to the library, with a brand new API being released every 12 to 18 months. Those new APIs and the breaking changes they introduce are the new shiny objects you can’t help but chase. You spend multiple cycles learning the new API and upgrading your application. It sure feels like you are doing something, but in reality, you are only treading water.
Just in the time that I had been coding React applications, the library went through some major changes.
- 2013: JSX
- 2014: React createElement API
- 2015: Class Components
- 2018: Functional Components
- 2018: Hooks
- 2023: React Server Components
By my reckoning, if you’ve maintained a React codebase for the past decade, you’ve re-written your application at least three times and possibly four.
Let’s take React out of the equation and imagine you had to justify to your boss that you needed to completely re-write your application every 2.5 years. You probably got approved to do the first rewrite, you might have got approval for the second rewrite but there is no way in hell you got approval for the third and fourth rewrites.
By choosing React, we’ve signed up for a lot of unplanned work. Think of the value we could have produced for our users and company if we weren’t subject to the whims of whatever the cool kids were doing over in React.
Stop signing up for breaking changes!
The Rule of Least Power
When building web applications, we should remember the rule of least power.
When designing computer systems, one is often faced with a choice between using a more or less powerful language for publishing information, for expressing constraints, or for solving some problem. This finding explores tradeoffs relating the choice of language to reusability of information. The "Rule of Least Power" suggests choosing the least powerful language suitable for a given purpose.
When building on the web, we could take this to mean that we should start with a base of HTML for our content, add CSS for presentation where necessary, and finally sprinkle in JavaScript to add interactivity and other capabilities that HTML and CSS cannot handle. React flips this on its head by starting with JavaScript to generate the HTML content, adding JavaScript to apply the CSS presentation too, and finally adding yet more JavaScript to apply the interactivity.
This contravenes the rule of least power.
Presentation
Here’s a simple React heading component.
function MyHeading({ children }) {
return (
<h2>{children}</h2>
);
}
It looks like you are writing HTML, but you are not. You’re writing JSX (JavaScript syntax extension). Fundamentally, JSX just provides syntactic sugar for the React.createElement(component, props, ...children) function
. So the JSX <MyHeading>My Heading</MyHeading>
code compiles to:
React.createElement(
MyHeading,
{},
'My Heading'
)
While you may think you are writing HTML, you are actually adding a lot of unnecessary (and possibly unexpected) JavaScript to your application.
Styling
CSS in JS libraries are very popular in React applications as they allow you to avoid learning CSS take a component-based approach to styling. The original CSS in JS library was developed by Christopher Chedeau, a front-end engineer who worked on the React team at Meta.
Let’s use JSS for our example:
import React from 'react'
import {createUseStyles} from 'react-jss'
const useStyles = createUseStyles({
myButton: {
color: 'green',
margin: {
top: 5,
right: 0,
bottom: 0,
left: '1rem'
},
'& span': {
fontWeight: 'bold'
}
},
myLabel: {
fontStyle: 'italic'
}
})
const Button = ({children}) => {
const classes = useStyles()
return (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
}
This is great because we’ve been able to co-locate our styles with our components, but it comes at a cost: performance.
A quick reminder of how browsers work: first, it downloads your HTML. Then, it downloads any CSS from the head
tag and applies it to the DOM. Finally, it downloads, parses and executes your JavaScript code. Because you have added your CSS declarations in all of your components, your JavaScript bundle is larger than it would be for a non-CSS in JS solution. This will increase the time it takes to parse your code just because of the larger bundle size, as well as the execution time due to the additional function calls to serialize the CSS.
We are drowning in JavaScript.
Use less of it.
This is not new advice.
Who’s running React these days?
No really. Who is running React? React’s last official release (as of this writing) is 18.2.0, released on June 14th, 2022. That was 19 months ago. To me, that signals that Facebook, er Meta, is no longer interested in pushing the library forward and instead, IMHO has ceded the leadership of React to the frameworks.
Is this a good thing? I’m not too sure. One problem with this arrangement is that Vercel is a venture-capitalist-backed startup, and they need to show a return on investment to their investors. As we’ve seen in the industry in the past year, VC funding is drying up. God forbid something happens to Vercel, but what happens to Next.js — and, to a greater extent, React — if Vercel disappears?
Additionally, there are worries about Vercel’s current stewardship of React. For instance, Next.js uses Canary versions of React because those are "considered stable for libraries." That seems quite odd to me. As well, Next.js overrides the global implementation of node fetch, which leads to problems — a decision that the Next.js team seems to be rethinking.
I’m not the only one worried about this, as the Remix team has forked React into their organization. No commits yet, but it makes you wonder.
Where do we go from here?
This post may feel pretty negative to you, and from my point of view, it was born of the frustration I’ve had dealing with React applications as a developer and an end user. Don’t even get me started on the GitHub rewrite, which doesn’t seem to be going too well.
Just so we are clear, you weren’t wrong to choose React for previous projects. It is/was a hugely popular library. Companies were hiring React developers, and you needed a job. No one here is saying you were wrong to use React to further your career.
However, here is my unsolicited advice:
- If you are starting a new project today, evaluate the other options like Enhance, Astro, 11ty, SvelteKit, and vanilla Web Components.
- If you are currently maintaining an existing React application, investigate how you can add web components to your project. Web components are library agnostic, so you can begin to future-proof your application. (Angular, React, Vue)
- Inquire how you can use HTML and CSS to replace some of the things you do in JavaScript currently.
Conclusion
It may seem hyperbolic to say that React is a liability lurking in your codebase, but is it? You are staring down an eventual React 19.0 release, which will introduce a number of breaking changes, forcing you to rewrite your application yet again.
Why?
Is it React’s vaunted developer experience benefits? Or is it the better user experience? Nope and nope!
My suggestion is to start investigating how you can remove this weakness from your codebase. Look at ways to de-risk what will be yet another rewrite.
And then level up even further by learning web fundamentals.
The web is backward and forward compatible. Anything you learn about HTML, CSS and browser API’s will serve you well for the next 25 years, which is not something you can say about the current fashion in JavaScript libraries. By ejecting from the thrash of React and other heavy-handed frameworks and doubling down on web fundamentals, you’ll be future-proofing both your career and your codebases.
Top comments (56)
Let me play the devil's advocate here. React is merely another framework. It has its strengths and weaknesses. It has seen many changes, but so have Angular(JS), Vue and more, while others have vanished altogether (remember Knockout or Durandal?).
Web Components require a lot of boilerplate and are difficult to debug. Lit eases a few of those problems, but it's not a silver bullet either.
At some point, even the most future-proof code becomes legacy code. So if you want to be really future-proof, have an exit strategy from whatever you are using now - even if those are web components already.
It doesn't hurt to separate view from logic, as tight coupling reduces portability. Also, you should be able to move to a new solution without a big bang approach. Pragmatic solutions go a long way.
Does anyone use ember.js still?
LinkedIn uses it.
React isn't a framework.
That shipped has long sailed dude. You're late to the party, React is a framework 😂
Is jQuery a framework too?
React is like an engine, jQuery is like a wrench. An application may run on react, but it could merely utilize jQuery. Only one of them enforces certain patterns.
I agree and disagree. React team calling it library so we should stick with it. However I agree with you it’s somewhere in between. I believe react team is working hard to change it to metaframework as once react-forget is out it’s not going to be just a library
This is still the same argument from authority fallacy. Just because they wrote a single framework they get to decide the definitions of libraries and frameworks for all of them? I certainly disagree.
In my book, a framework is something that shapes the code run within it. By this definition, React is certainly a framework, despite its community may claim otherwise.
However, none of them could give me a convincing definition that would exclude React. Let's hear yours.
React is a Library, not a framework. React is essentially a collection of classes and functions that make things somewhat easier/quicker to get development off the ground. A framework is more a platform that provides a foundation for building applications, providing structure etc.
There’s a lot of good write up's on this topic!
In those write-ups, the distinction point is inversion of control. But even so React takes up a large chunk of control over the DOM and even over fetch, which fulfills the definition more than e.g. AlpineJS, so I think you're still wrong calling React a library.
I'm really not sure what the whole "it's not a framework, it's a library" posse should bring. Should it look like it's less opinionated? Or less constrained? That would be rather amusing, I guess.
You are trying to make subjective opinion into fact - React is a library and this is the official description of it from the devs own mouth. End of story.
I'm making an argument here, not stating an opinion. If you can't make that distinction and address the argument with valid criticism, you're not adding anything of value to the discussion.
Also, if the devs officially declared that it was a chocolate cake, I still wouldn't eat it. This is an appeal to authority fallacy, not a valid argument.
React isn't just a framework, its an ecosystem ..it long outgrew the boundaries of frameworks
Other frameworks have an ecosystem, too. As a member of the Solid.js ecosystem team, I should certainly know.
Nice try, but you get no extra points for attempts to confuse the matter.
yeah yeah
I like these kinds of posts because they make me think, but at the same time I don't think they provide too much value beyond provoking discussion. Let me go point by point.
JSS is completely optional and you can use any other styling solution with React, including CSS modules and Tailwind, which also collocate styles with components. This is nothing React specific.
Saying React has a Shiny object syndrome and comparing it to new kids on the block like Astro doesn't make sense to me.
I agree with the Rule of Least Power, and one should avoid using JS where HTML/CSS suffices. That said, JavaScript is indispensable to create and manage non-trivial UIs. It's insincere to blame React for "JS first" and compare it to Svelte or Web Components which themselves wouldn't fly one bit without JS. In the end, all content that's not directly returned from the server has to be JS generated/incorporated so your criticism of React is actually complaining about how the web platform works. However, debating which content has to be generated on the client and which doesn't is always a valid discussion.
About new versions of React breaking apps, well not really. React is not Python, it maintains a great level of compatibility with the older versions. If you have used
React.Component
6 years ago, you can still use it today and avoid hooks altogether. Of course React's APIs changed a lot in its 10 years existence, but I'd rather highlight how astonishing it is that it remained relevant to this day. If you compare it to other established frameworks like Angular or Vue, which had their fair share of big changes too, maybe it says something about the nature of people and projects evolving, and I think you are complaining here about "not getting things right the 1st time" which is a classic mistake to make.Your frustration with React that you linked is in reality a frustration with engineering teams not caring about bundle size. You can't blame React for that, bloat can be created even out of Vanilla.
I think your criticism of React is mostly invalid and recommending Web Components as an alternative seems counter productive to me. They have quite many unexpected pitfalls, are quite clunky to write without a framework and again, they are JS first regardless of how shiny they might look at first glance.
I agree that it's good to think critically about which libraries get used for a project. However, I think there's a couple things to point out here:
That's really what I'm trying to get at with my somewhat inflammatory post. It would be great for folks to evaluate or re-evaluate the frameworks they are using since a lot has changed in the past five years.
Not sure if there's anything particularly unique to be honest. Migrated a vanilla js project to React 15.3.2 in 2016 and use 18.2 in projects now.
As far as I know, class components stayed pretty much fully backwards compatible throughout that time. The only real pain point moving to hooks was some event listener & canvas/DOM cleanup that used to be in
componentWillUnmount
and didn't translate perfectly as a return function inuseEffect
.Outside of React, ran into some limitations/frustrations with react-router and switched to using Next.js for new projects last fall. Overall very content with that choice so far, but it was a bit of a hassle to adjust to at first.
In terms of structuring projects, I've typically aimed to keep the scope limited (e.g. split a large platform into its constituent parts) and made private
utils
andui
NPM packages to share between them. Keeps things lean & centralized overall I think.I definitely get what you're saying, but if you leave the Vercel question aside, what you wrote is just as applicable to Astro, Svelte, Vue, etc. In fact it's also applicable to Web Components which are written in JavaScript.
It is much less likely with web components since they are part of the platform and their API's are stable. There will only be additive changes to the API's, no breaking changes. A web component you write today will work unchanged in 2039.
I don't think that's necessarily true. Firstly, you can still run React code from 2015 - it works just fine in nearly all cases. And I don't believe they plan on deprecating the class-based API.
And secondly, most people building with web components are doing so with lit, which has exactly the same issues. It's currently on version 3, which in theory means three sets of breaking changes. You can build web components without lit, but it is a MASSIVE pain to get anything resembling a functioning component-based UI.
So the only bit about the post that is a practical difference is the affiliation with Vercel, which I agree is very awkward and a valid reason not to use React.
The difference being, web components will probably never be legacy tech, but React definitely will be.
It depends on how you build your web components. As I said, most people still build web components with a framework like lit or stencil, and those could absolutely become legacy tech. There are not many people building plain web components - at least not for whole applications or complex reactive components - it's just very fiddly.
Great article.
There are more issues with the modern React which I mentioned here: dev.to/arturampilogov/react-is-not...
Today we do not have a good alternative. Only HTMX heavily fighting the whole concept and JS app architecture approaches.
Ideally Web development should include:
1) New version of HTML with concepts from HTMX, so that there is no need in JS for most cases.
2) CSS already provides many cool UI features ✅
3) A new modern language that compiles to WebAssembly as close a possible. It will allow to write server-side logic (supported by any platform) and extra dynamic front-end code.
In my opinion, the problem lies in the frozen front-lines of the Browser Wars. JS is a flawed language, with many quirks that waste so much time for every new learner.
CSS was built for styling documents, not for richly animated, interactive UIs.
A truly big paradigm shift would be to repurpose the browser to be it's own heavily sandboxed OS maybe where you can bring your own language to.
Whole HTML ecosystem is going from simple document to a ( maybe richly animated ) interacive UI. In greater perspective no mather which technical solutions reach this goal. If you are against JS then HTMX is your way. In my perspective the react give a great frame for interaction/animation heavy solution on FE side, where I can combine classic HTML with SVG, WEBGL, Streams interaction/animation elements, for a performance optimal result. If I care so much of amount of JS then I will use
qwik
.See my answer to Joshu Amaju please.
lol, let's throw away the language because you have a very niche use case.
I feel you and Peter Vivo think about this emotionally. I had the chance to use a couple of programming languages professionally. JS has objectively a lot of quirks like an absolutely inconsistent "array" of array methods like
sort
is mutating the array whilemap
is not. And so on.Many would have been happier to use their choice of language, but unlike in an OS like MacOS or Windows, in the browser you can only use JS or things that compile to JS. For example for the mission critical performance tasks you have now things like Rust and Zig and not just C++ or C. These are recent, modern languages. They can exist, because the platforms they are on are not stuck like the browser world.
Regarding interactivity: CSS has similar problems: during its long life it got repurposed many times. I bet some big money on it that if people had to create a new UI engine with a new language it would be a lot different than what we have currently.
This does not mean that either language is garbage, but we are at the point when people don't even consider anything else. We have learnt a lot about what works and what not in programming languages and yet we are stuck at JS for better or worse.
Coming at your interlocutor saying their statement is one derived from emotion is a great way to pass your point across...said no one ever.
I bet you can't come up with one valid reason we should ditch CSS, my observation is that most people that complain about CSS just don't know it, rather than try to understand it they complain. But you can prove me wrong.
JavaScript has issues, but most of the critics are just "I can't put in the work to understand this thing so I'll just complain about it". I've never had issues with anything you've mentioned.
And you do realise that some languages these days are following in the foot steps of CSS and Javascript? There goes your bet.
And if you really want to avoid using Javascript on the web, you can actually go build your own browser that supports different languages. You can also use compile to Javascript languages, you have options. So I don't get the issue. Or is your issue that you don't want Javascript to exist?
Sorry man, your reply is very combative, again, coming from emotional attachment.
I should not do it, but I do reply on your claim about CSS.
Name a cutting edge AAA video game that uses CSS. None. CSS was built for styling documents. It's excellent for that. Many people are forcing their CSS-in-JS way through it avoiding using the defaults that makes CSS very lean (when understood well).
However the problems with CSS will arise when you have to quickly rerender many things at scale. CSS was not designed for very fast rerendering. In fact, being a code JS engineer is to know enough about the DOM and how CSS works to avoid rerendering. But with different languages, rerendering is not an issue at all (unless you do something very stupid).
Nowadays you can do things on top of the current engine that allows you to do run effective and optimized animations in the browser, as an afterthought.
Please show me a AAA video game which is running on browser. I think this is does not tightly belong to HTML/CSS/JS architecture. If you would like to making a smooth and really GPU intensive graphic then you would go to WEBGL. But show me AAA video game which social platform is not on the web. Because HTML/CSS is much more related to document, social platform - like this one or discord.
But in my use case - reall industial one - it is also great ( including react ) to make a high frequency scientict realtime data handling application building. Which is of course use WEBGL, interactive SVG animation, CSS, HTML. Everything which need to use scientist at daily work. So I think this technick is not so slow as you imagine.
At this point I don't take you seriously cause your arguments are based on emotion.
I think you'd like Alex Russel's article The Market for Lemons.
We are big fans of HTML-first approaches and server-side rendered web components that lean on the light DOM. Here is a shameless plug for Enhance, an open source project I work on.
This is unlikely, 25 years ago people would use framesets and other ancient stuff, which modern browsers won't even support.
True, but a lot has changed for the better. I still use paddings, margins, classes, methods to name classes and so on.
We're talking about a slow incremental replacement of the dumb stuff with smart stuff.
For the past nearly three decades if not longer, browsers have understood three languages: HTML, CSS, and JavaScript. Everything that runs in the browser is written in one or more of those languages.
Now we have WASM and a few other languages, but the vast majority of the Web remains HTML, CSS, and JS. TypeScript adds static types and inferencing, but does not (currently) run natively in the browser.
So React, Svelte, Solid, Angular, etc. are just HTML, CSS, and JS. Seventeen years ago I was building websites using Scala to generate HTML, CSS, and even JS. Before that it was Ruby on Rails. Before that PHP and before that CFScript.
But in the end it was all just HTML, CSS, and JS.
So everything we add on top of those three languages is just baggage. It slows things down. It adds complexity. Just as Eric Elliot mentions the "TypeScript tax", there is a "React tax", an "Angular tax" (quite steep), even a "Svelte tax".
What I want is easy re-usability and a component architecture. Simple routing is nice, too. And static types.
Astro with TypeScript provides all that. I don't need or care about the "islands" feature. I use no client-side dependencies except the occasional polyfill.
But Astro let's me write components and reuse them without having to resort to Web Components, which remain difficult to use and, IMO, overly complex. I may eventually use them, but not until I must. Meanwhile, I look for easy ways to abandon Astro, too.
I was an early adopter of React. I taught the first React class at Codementor (now Arc). I pushed my employer at the time toward functional React, then FRP (redux-observable), then hooks. I taught state-of-the-art React to hundreds of people.
But I abandoned React five years ago (except when forced to use it by contract). And when forced to use it, I stripped away all the bloated ecosystem cruft.
I describe this process on my website, Craft Code, for anyone who is interested. The site itself is vanilla HTML/CSS/JS built with Astro and TypeScript (and some Vercel serverless functions).
A great many devs have invested heavily in React and its ecosystem. It remains to be seen how many even remember much HTML, CSS, and JS. They will not easily surrender their investment. But beware the sunk cost fallacy. For the vast majority of sites/apps, React and most other frameworks are overkill.
And your HTML/CSS/JS is unlikely to need to be rewritten every 2.5 years. CSS and JS improve yearly, but there is no need to rush to embrace those new features. So we're talking serious shelf life. But I guess if you prefer refactoring to writing new things ...
I'm reasonably happy with this state – perhaps for the first time in decades.
You can build a React application and not touch it for 10 years and it will be just fine... In my experience though, most enterprise apps don't live longer than 3 years before getting complete replaced or rewritten. So your argument that is somehow weird seems really weird to me. The web is fast paced. Nobody ever said it wasn't. Also, you don't have to rewrite your application to use React server components. What you do need is a full stack framework that supports them though. There are no breaking changes in the way React works since v16.8 and infact it still remains backwards compatible with react code written before that so... Show me another framework that is backwards compatible with code written nearly 10 years ago.
I'm so frustrated with relearning every 3-4 years a new paradigm. Only my CSS and SQL skills seem to be long-lasting.
But then you have people making sure you can't use either because here's instead a framework with religious followers "simplifying" these languages that are going to be gone in 3-4 years again (I'm looking at you
Tailwind
andPrisma
).I´m not sure that your are right about page rendering:
Before any element is processed, the page is scanned for external references, so they can be fetched while the page is being processed.
But all Elements on a HTML page are just processed in the order they appear. A ascript placed somewhere in the middle of your HTML-code will not be able to access any DOM element, that is defined by HTML somewhere below. So, HTML and JS on the same page are executed in the order they appear. They both will build the DOM-tree.
Building the DOM and rendering the DOM to the screen are two different things. Before any part of the page can be shown, CSS needs to be fully loaded and read. If it is an external CSS-file, this might be after the DOM is ready.
Things get much worse if not all external files are referenced in your main page. Then you might get a chain of files, each needing to be fully loaded and executed before you can start to fetch the next file. This can end up with a reasonable delay.
There are different things that can delay your page. It is more the order and structure of the different modules you need than just about a single reason. If you say: "avoid Javascript, it makes your page slow" this is might be a bit misleading.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.