React is bad because it's great

September 22, 2022 on Eric Bower's blog

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

https://marmelab.com/blog/2022/09/20/react-i-love-you.html

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 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.

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 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 become disillusioned but it and start looking for simpler alternatives.

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

the black box

I try really hard to at least make a cursory glance at the libraries I use. I’ve learned a great deal about programming by taking the time to read library source code. 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, and I read all about fibers when they were released. Now we have hooks, SSR hydration, server components, suspense, concurrent mode, react compiler … the list keeps growing over time.

Furthermore, since so many people use react, there’s a great sense of responsibility to not break backwards compatibility. This is a doubled-edge sword. On one hand, end-developers are able to upgrade react without too much headache. But on the other hand, changes that were proposed years ago are still being implemented.

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

However, it’s now an impenetrable fortress and the time investment to learn the internals is not worth it 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 a better solution.

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.

conclusion

I do still really enjoy react and it’s still my recommendation for building web apps. 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.


Articles from blogs I read

Generated by openring

How to help improve SourceHut's design

SourceHut is a software development forge and it is designed with the software engineer’s needs first and foremost. The design prioritizes things like page speed, minimal distractions, and information-forward layouts. It does not prioritize aesthetics, and p…

via Blogs on Sourcehut October 13, 2022

In praise of ffmpeg

My last “In praise of” article covered qemu, a project founded by Fabrice Bellard, and today I want to take a look at another work by Bellard: ffmpeg. Bellard has a knack for building high-quality software which solves a problem so well that every other solu…

via Drew DeVault's blog October 12, 2022

Site Update: HLS support

Hi blog readers! It's time for a regular update on stuff I've gained expertise in frantically googled and hacked together so I can put it in front of your faces. I use YouTube as a video hosting service because it's largely predictable and it'…

via Xe's Blog October 11, 2022