React is bad because it's great

on erock's blog

A reply to a recent article about react

There was a recent article that made it to the top of hackernews yesterday that I felt was interesting but also didn't resonate with me.

I wrote an initial response to this post on twitter but feel the need to write a longer post about it:

React is frustrating because it has accumulated a decade of debt, added a ton of complex features and continues to grow in size. It’s a black box that is so complex that it will eventually buckle under its own weight. Most insanely popular libraries share the same trajectory. — Eric Bower (@neurosnap) September 22, 2022

First, all of the reasons for why react is awkward or difficult are true.

The main criticisms are:

I agree with all of these criticisms, but ultimately they aren't the reasons why I'm starting to dislike react.

The reason why I'm starting to not like react is because of the tech debt it has accrued over a decade of being the number one view library for the most popular operating system on the planet: the browser.

You can't be one of the most popular libraries on the planet without becoming a magnet for a million use cases. React has been wildly successful because it has adapted and grown to satisfy the needs of so many businesses. It has worked so well that is has become a complex, black box machine that is impenetrable to most end-users.

I've noticed a similar trend with many popular libraries over the years. They are never "feature complete" and continue to grow in size until they are so large that people start liking the idea of simpler libraries. These simpler libraries start small and then over the years grow into the thing they were trying to differentiate themselves from. How many libraries boast small code sizes in the beginning but then grow so much that they have to remove that "feature" from their list?

Keeping popular libraries limited in their feature-set takes discipline that most of us engineers don't have. Why would we? We love writing code! We want to write code!

the black box

I make it a habit to read the source code for most libraries I bring into my apps, it's a great practice to learn how to read code as well as understand the potential limitations of it. However, react is one of those libraries that is far too complex for me to invest the time. I read the RFCs, I read some of the pull requests, I read all about fibers when they were released. Now we have hooks, SSR hydration, server components, suspense, concurrent mode ... the list is growing over time. Changes that were envisioned when Svelte's team articulated that the virtual DOM was "pure overhead" and rethinking reactivity are still being implemented in react, 4+ years later.

React has to move slowly because so many people depend on it working well. I really respect the react team for keeping backwards compatibility while at the same time making progress towards new features, but I hate how difficult the ecosystem is becoming to navigate.

In the beginning I loved react because the API was powerful but concise. The initial implementation could be written in less than 1000 LoC (I've written it before).

However, it's not an impenetrable fortress and the time investment to learn the internals is not worth is for most end-users. Maybe that's okay, but it's a big reason why I don't like react as much anymore.

side effects

The beauty of react can be described by a single function:

const view = func(state)

View is just a function of state. This paradigm shift allowed us to go from an imperative-style, direct DOM manipulation towards a more declarative style. We were able to assume our page was re-rendered on every state change.

This made the code easier to write and read. However, this was a lie. React is not declarative because our functions produce side-effects. From data fetching to event handlers, our react components produce side-effects which transition us from declarative (here's the html to render) to imperative (when an event happens run this function and manipulate state).

React doesn't handle side-effects particularly well and its impurity has lead to a lot of awkward situations that the cited article above articulates.

That's great, erock, but what's the alternative? It's not fair to say something sucks without presenting an alternative model.

The solution is to create pure functions that don't produce side-effects at all. The solution must take the entire picture of rendering html without ignoring data fetching, event handlers, state transitions, etc.

Really, what I want, is a solution that generates views based on a stream of events. Think about it, events could be prop changes, state changes, a user clicking a button, fetching data, etc. I don't want a view that is a function of state, rather, a view that is a function of an event.

const view = func(event)

The closest things we have to that today is cycle.js.

The downside is I'm not a huge fan of observables. I think a potentially better solution to observables would be sagas. Functions that leverage the power of generators to respond to events and render HTML as a result. That plus the fact that sagas do not produce side-effects could make for an interesting paradigm shift in how we think about our views. You mix cycle.js, sagas, and elm's model-view-update paradigm and you might have something interesting.

corporate alignment

Vercel and the React team are working too closely together. When I read the announcement about server components and how the react core team was working "closely" with the next.js team to deliver server components first, I felt myself less excited about it.

Why should I be less excited about the most popular view library partnering with the most popular react framework to release server components? Because now next.js is cornering the market and suppressing competition in the space. It is fostering favoritism for one particular framework that not everyone uses or wants to use. I understand the potential value but it really does feel like a conflict of interest. Vercel is profiting from being first-to-market for a new react feature while excluding everyone else from the initial participation. The feature itself is being manipulated by a company that has a vested interest in pushing their cloud platform.

It's hard to articulate why it's a problem, but I really don't like the favoritism here. At the end of the day, maybe it doesn't matter. However, react is part of facebook and next.js is part of vercel. We shouldn't kid ourselves what the ultimate motivation is here. Creating a better library is secondary.


React is bad because it is great. I do still really enjoy react and it's still my recommendation for any company I work for. In my free time, however, I'm looking at alternatives. I'm starting to question its complexity when other libraries are able to do the same -- or more -- faster and with more interesting paradigms. React also doesn't handle side-effects well and instead creates escape hatches. Furthermore, corporate interests are driving feature development in a way that makes me feel like ulterior motives are getting involved.

Have a comment? Start a discussion in my public inbox by sending an email to ~erock/