A few poorly-reasoned rants to express my feelings on React.
Community support on Reactiflux discord is primarily awful (no offence to the
people who do help). The main channels suffer from what you could call the
#ubuntu
problem: excessive demand, no supply. Lots of noobs ask poorly
formatted unclear questions and as a result, users with the requisite experience
to answer the relevant questions don't have the patience to monitor the channel.
As a result, even asking extremely clear questions with definite answers don't
get the same response as you would get on (for instance) #c++
on freenode.
No guidance on how to structure applications. Again, #NOTAFRAMEWORK caveat, but in some ways this is like building a gun without a safety catch; if your thing X causes someone to die when it's used wrong, and it happens to be used wrong in 99% of cases where it's used, does that speak well of the thing? There are a set of best practices in the community but nothing that's really agreed-upon or endorsed, and it's near-impossible to come to a fresh React codebase without doing huge amounts of spelunking. Vue makes much more sense in this regard. Even though I can't pin down a precise technical reason for it (SFCs? docuemntation?), in practice project X is far more likely to be structured similarly to project Y in Vue than React.
Unacceptable levels of boilerplate when creating forms. I don't think I need to demonstrate, even React fans admit that it's not where the toolkit shines (and Vue competes badly here too when Vuex is in use; AngularJS is better). APIs like Formik are ludicrously complicated for what they do. I think that traditional server-side web frameworks are far better at handling applications that are basically forms, which is a surprising number of applications.
There are patterns labeled as "advanced" that are completely necessary to the
day-to-day usage of react. eg, HOCs, render props, children
. Even Redux is a
fair example. "But you can get so far without these!", I hear you cry. You
can, but do you want to? Will what you've produced have any value if it's a
write-only mess? Also, what the hell is a Saga and why do I need it?
Create-react-app sucks with its 'eject' concept. Why say: "Stick 100% with the preset, or completely dissociate from us and never get any updates"? Surely it's not beyond the wit of man to form an abstraction on top of the C-R-A tooling that allows SOME conditional behaviour but is robust against upgrades (by which I mean, loudly complains when upgrades will break)? Instead they go with the Mac philosophy of pre-canned-and-designed-experience or nothing at all, and I feel like that's essentially out of what can be called laziness or, more accurately, unwillingness to invest time and thus money. Surely FB has enough of those two resources? (For an aside here, see Two Categories of FOSS Project.)
Everywhere in the frontend world and in React too, you get this boosterish, marketing-adjacent attitude, showing up in the documentation:
Apollo Link is easy to use with a variety of GraphQL libraries. It's designed to go anywhere you need to fetch GraphQL results.
The first sentence is OK, though pretty much unnecessary; the second sentence is
rage-inducing. We're programmers, can't we just communicate clearly? All the
"Made with <3" and emoji abuse throughout the documentation has the same
alienating effect. I know I'm old, but just give me an HTML4 page with <P>
tags and no styling; that's when you know the
software is quality. (Ideally it was written by a 65-year-old academic in
emacs.)
There are still race conditions in the webpack TS watcher to this day that make it incredibly frustrating to work in large TS codebases. This is largely the result of bit-rot, which in turn is the result of the VSCode monoculture not caring about command line tooling. Many frontend developers just do not care that their whole setup is radically dependent on editor choice. Not only this, but this specific issue is one that is extremely difficult to find a community space even to talk about, because it's the intersection of 2 different infrastructure -- Webpack, which plenty of people do know about but very few people want to know about, and Typescript, which only happens to be slow enough to more-easily trigger this particular latent issue.
Not React-specific, but Apollo forces your API into weird shapes. When I do
useMutation
I am recommended to put callback for error handling into THIS
call, the call for the hook, rather than the place where I actually call the
mutation. This isn't the normal pattern in software.
Every time you want to do a conditional or a branching statement you
essentially have to factor the conditional into a new functional component, that
or use an ugly ternary. Again, very principled, but not very ergonomic. The
lack of first-class IDE support makes this one a particular pain, since it shows
up constantly. I find myself hoping that the business domain logic can be
expressed as a simple foo() && <bar/>
just so that I can avoid factoring out
yet-another-conditional.
In some ways React reminds me of Clojure, which is both good and bad. A single basic unit (the JSX expression, or component) that's endlessly composable in principled ways. The problems it has are also ones that Clojure codebases can show: a lack of standardization of any particular structuring method, so the overall arrangement reflects the particular mental quirks of the author. The syntax of Clojure is more attractive to me, and certainly much less verbose than JS, even though syntax should certainly not be the focus in Lisp. React is really fairly readable at a micro level, provided that the author wasn't insane, but at a whole-application level it is far more challenging to reason about than most people will admit, and this is partly due to the relentless decomposing that the functional style forces. It's not so bad in Clojure, I think because Clojure backend code is fundamentally about data manipulation which puts an upper limit on the level of the call stack you can need while still having a good design. In React there's no practical, conventional, or aesthetic limit to the depth of that call stack. And pulling parts out from deep inside the structure is mostly a massive pain, where in Clojure you can just use the REPL.
Update 2024: I have found a link for the gun-concept discussed above: POSIWID.