Published: August 4, 2023
Updated: August 9, 2023
Part 1: an intro about music, defaults, and bubbles
Like a lot of people, there was a time when the only music I listened to was whatever was played on my local radio station. (A lot of people over 30 or so, anyway. If this doesn’t sound familiar to you yet, just stick with me for a minute here.) At the time, I was happy with that. It seemed like all I needed.
Looking back, I realize: I naively trusted that anything good inevitably became popular—and therefore, anything worth knowing would eventually come my way on its own.
Eventually, though, other music began to take root in my life. Through new friends and the internet, I became acquainted with new artists, further and further from the things I liked before—or, at least, thought I liked.
This music was different. I wasn’t in love with it one week and sick of it the next. Listening to it wasn’t part of an endless cycle.
If anything, it was the opposite; it was music I actually liked and appreciated more the more I listened to it. There was depth to it. Sure, it didn’t have the loud distorted guitars, punch-line lyrics, or sugar-coated melodies I’d enjoyed up until that point. But to my surprise, that actually somehow made it better, not worse.
That’s when I began to realize: maybe I was never really as satisfied as I thought I was.
Maybe my bliss was, in fact, predicated on ignorance.
Finding richness beyond the defaults
I suspect you can probably relate to that story, even if it’s not with music specifically.
Most likely, you now count a food or drink you didn’t once like among your favorites. Or, maybe you were surprised to find a movie, book, game, podcast, influencer, or hobby you didn’t expect to like resonated with you.
The details aren’t important; all I’m getting at is:
You’ve probably experienced finding something great beyond the periphery of popular defaults.
Not to sound like a frontend version of a snobby hipster. That’s not my intention. If your idea of a good time is Bud Lites at Olive Garden: cool, pass the breadsticks.
But what I am trying to do is: gently share the idea that maybe you’re shutting yourself off to something great, without even realizing it.
Maybe this whole concept—finding better things beyond familiar boundaries—applies to our tools and workflows just as much as it does any other area of life.
And maybe—just maybe— your current satisfaction comes, at least a little bit, from simply not knowing what you’re missing.
Completing the analogy, and acknowledging its shortcomings
I’ve written before about how React is the new default frontend framework, and how I don’t think most people using React on a regular basis realize quite how much it’s fallen behind.
And on that note, this is where our analogy begins to fall short.
Assuming we were only talking about personal preferences, I’d never write a blog post arguing about what you like, or trying to change your mind. (Not at this age, anyway.) Who cares? If you enjoy it, have fun.
But unlike music or other subjective things meant for our own enjoyment, our choice of frontend tools has empirical, measurable effects on others.
That decision carries a real responsibility. It’s not just about what we like. When it comes to development—unless we’re building things purely for ourselves, anyway—our enjoyment is secondary; the user’s experience is what matters most.
If you love your tools, that’s wonderful. I hope you do. But that’s a side quest at best, and a potentially harmful distraction at worst. Developer experience (DX) shouldn’t ever supersede user experience (UX).
So forgive me for choosing a flimsy metaphor. You can keep listening to the same music for the rest of your life, if you want to. I support that. But we have very valid and important reasons to push beyond the comfort of our existing preferences when it comes to the tools we use.
The React bubble
The idea that React lags behind its peers might be new to you. Like many, you might still consider React the modern standard in frontend. So let’s quickly poke at that bubble, in this one last section before we get into the titular list.
This, from Alex Russell, via Mastodon, is what started me writing this post:
Someone asked me today if there was a case for using React in a new app that doesn’t need to support IE.
I could not come up with a single reason…
It’s astonishing how antiquated React is.
Alex mentions React’s lack of support for web components in that thread. That feature has been glaringly missing from React for years. And yes, it’s “on the roadmap.” As of this writing, though, there’s no firm commitment to either an implementation or an expected ship date.
Meanwhile, pretty much all of React’s contemporaries—any framework or technology you might choose instead of React—already have that story shipped and in production.
Web components are one thing. But they’re far from the only item on the list of “stuff everything else does already and/or better.” (We’ll cover several others below.)
React benefitted mightily from being early to the framework game; it set the standard. But that’s come with severe drawbacks in agility and adaptability. Every decision React’s made since its inception circa 2013 is another layer of tech debt—one that its newer contemporaries aren’t constrained by.
React is ‘13 tech designed to ‘08 constraints. Nothing about it is innovative in 2023; in fact, it’s the slowest way to get functional-reactive frontend programming in the modern era…
React has aged, and how I don’t think most people realize how much or how poorly. So to put the quote above another way (and tie it back to our intro about music):
React was designed seven Taylor Swift albums ago, for a world where John Mayer and Jennifer Aniston were still dating.
(Seven new Taylor Swift albums ago, that is. That doesn’t even count the Taylor’s Version releases.)
So if you’re one of the many developers whose whole world has been React for the past few years, there might be things you’ve forgotten—or never knew at all—because you’ve been using React for so long.
As fast as modern frontend moves, we seem to be very slow in realizing the world which crowned React king, in many ways, no longer exists. (If it ever did; not many organizations had anything resembling Facebook’s specific set of problems to begin with.)
Browsers have seen wild growth in new feature adoption in the last ten years, in both JavaScript and CSS. Technology and user expectations have evolved, and the current ecosystem of tools has done a lot more than you might think to iterate and adapt past React, in ways such legacy software can’t.
I realize calling React “legacy software” is controversial, but I think it’s fair; it’s comparatively complicated, relatively old, contains a lot of rules and gotchas, beginners are often afraid of it, and the architectural decisions it’s built on top of have long since become an impediment to its ability to iterate.
If I haven’t completely alienated you yet by this point (with some combination of quasi-elitism, rambling preamble, and overuse of parenthetical interjections), I’d like to share some things you might have missed if your head’s been entirely in the React world for a while, in the hopes of introducing you to some tunes you might be surprised to find are better than what’s on your current playlist.
Part 2: things you forgot (or never knew) because of React
I’ve touched on this in other posts, but any time an “unproven” framework’s name comes up as a potential tool for a dev project, the first question anybody seems to care about is: how big is the ecosystem?
You might have even had that thought as soon as you read the premise of this post. Move from React to another framework? Are any of them big enough yet?
Why do we have this obsession with ecosystem size?
Sure, we want to be certain this framework won’t just vanish on us, or stop being maintained in a few years. That’s perfectly valid. And yes, we wouldn’t bet the farm on something too new or unproven. But Vue, Svelte, Preact, Solid, Astro, and others are all far past that point, well-supported and well-maintained. So it clearly isn’t just that.
So what is the sticking point? I have a theory:
We’ve been trained that packages need to be built specifically for our framework.
You could reasonably argue that mindset started with jQuery, but I think React accelerated it.
With React, any time we needed a module or a widget or a library to do something specific (a carousel, a map, an accordion, or whatever else), it had to be a React thing; a plain web thing or a vanilla JavaScript thing just wouldn’t do. All of React’s rules and handling of state and quirks of component lifecycles meant that any available package or library which wasn’t explicitly written for React probably wasn’t going to work.
React trained us that things need to be built specifically for a certain framework. But that’s not very true anymore, and it arguably never should have been.
We shouldn’t need to do that—especially for a framework that so often claims it’s “just JavaScript.” If it’s just JavaScript, then it should just work with anything that’s actually just JavaScript.
Sure, other frontend frameworks have their own rules and conventions about state and architecture. You can step on figurative rakes in their yards, too. And yes, there will always be things that are, and need to be, built specifically to work with Svelte or Vue or whatever else.
But crucially—and I want to emphasize this as strongly as possible:
No other modern frontend framework is as stubbornly incompatible with the platform as React is.
If you’re building using other modern tools and frameworks, it’s far more likely that the vanilla JavaScript packages available will work just fine for you—and there are thousands of them. They’re far less likely to cause issues with render cycles, or other framework-specific issues. Not to mention: they all have the option of using web components, too.
You often don’t need a specialized package or library tailor-built for your thing, because your thing probably already works with the platform, and therefore, everything else that’s already out there.
Preact Signals is a phenomenal example: although built for use with Preact, it can be imported and used in any framework, or even in vanilla JavaScript. Web components, too, are compatible with just about any modern non-React framework.
Where the frameworks fall short, it’s likely the platform already has the thing you need. (Form submission, for example; always a pain point in React, now made infinitely easier by two-way data binding and just using the conventions browsers give to us.)
And worst-case, it’s probably a lot easier to build whatever thing you need than it was in React. (It shouldn’t take very much comparing of useState
with other frameworks’ versions to see that.)
Being newer is often considered a disadvantage by conservative-minded developers who are wary to test the waters with something that hasn’t been thoroughly vetted in every which way possible. But it’s important to remember that being new is also an advantage, because there’s less tech debt and old browser support to worry about—and new things are free to iterate further on existing good ideas and more modern browser features.
React hooks are actually kind of outdated
Hooks are the newest evolution of React, replacing class components.
Credit where it’s due: hooks were a massive shift in the frontend space. They revolutionized how we composed logic and state in our applications. Hooks are undeniably great, and pretty much every framework has coalesced around a hooks-like model for managing state.
But React hooks aren’t new anymore. (In fact, stable React with hooks is almost exactly the same age as my kid, and he’s starting pre-k in a couple of weeks.)
Hooks are no longer a competitive advantage, or even a notable feature; they’re the baseline. They’re just the way we do things.
Every other framework not only has its own implementation of hooks, but notably: every one of them is faster, smarter, easier to write, or a combination of all three.
Preact’s Signals warrant mention here; so do Svelte’s dead-simple stores. Solid, too, has Signals. Even Vue 3’s composition API, which is pretty directly inspired by hooks, has some key advantages over the React implementation.
Hooks are an excellent pattern, and React deserves credit for popularizing it. But pretty much every other framework does hooks better, with fewer rules, and with less boilerplate.
If you’re unfamiliar with the concept of Signals: it’s a crude oversimplification, but you could think of them as the next, better evolution of reactive state; an update to hooks, with better defaults around what causes re-renders, to only re-render the nodes that need to be re-rendered, instead of entire components.
You don’t need to micro-manage rendering anymore
I have a confession to make: I’m still not exactly sure what the difference between useMemo
and useCallback
is—or wh