What is React really like? Part 2
Note: these are just my honest opinions as a vanilla / Svelte dev trying React out on a real project. Not looking to have a war with anyone on this
Ok, I said I'd give some little updates as I went, but honestly, I didnt have time because I was fixing soooooo many Typescript issues.
That's a bit of a joke, and a little bit true. There's a lot to say, so if you dont want to read it all, just read the first two sections.
How did it go?
Did I try to learn too much at once? React, Next, Tailwind and Typescript. I essentially hadnt used any of them before. I had a pretty steep learning curve.
For example, the errors in the terminal meant nothing to me. When there were errors. It felt like the feedback would either be "catastrophic error", or silent errors skuttling my code in the background. And it wasnt always clear (to a beginner) if the error I made was a Typecript violation, misusing Next, or a fundamental React issue.
After a while, I did start getting the hang of it. I was able to put a component together pretty comfortably, and understand how to fix errors.
How did it turn out?
Now that I'm used to it, do I like the React ecosystem? No. I truly feel like it's a relic of a particular time, and isnt at all optimal for the tools we have now. I think users and developers alike are the victims here, and only that it appears to make hiring easier, therefore more juniors learn it, it survives.
Within that, then, I think the weight of the React ecosystem mental model is so heavy that devs feel they cant take on the mental weight of another framework.
On to the details.
Worries before starting
In my first post I had a few things, lets see if they did.
Worry 1: CSS is supposed to be weird.
I love CSS. Styles, neatly cascading, intertwining, overriding and eventually displaying a neatly choreographed UI? * chefs kiss *
The change to Tailwind was jarring. My first note was that "Tailwind feels like it doesnt want to use the cascade". Of course, with purely utility classes, that's true.
Like with everything else in this project, I got used to it. That said, I did have to escape a lot of Tailwind's own set classes (eg p-[1.5rem]). I also used global.css to write a class or two, for a grid system and some reset styles I didnt agree with in Tailwind.
There are limitations with Tailwind.
Poor recommendations from the docs
They dont recommend using :before or :after. "It’s worth noting that you don’t really need ::before and ::after pseudo-elements for most things in Tailwind projects — it’s usually simpler to just use a real HTML element.". They recommend using spans instead.
This is mind blowing, and I feel bad practice. These pseudo elements, even in their example, are purely for display. :before and :after are exactly what should be used here. I feel the developers realised they couldnt make this neat in Tailwind, so recommended something worse.
Missing selectors
Not only bad advice, but a whole class of selecting is lost: :first-child. Sure you can add first:____ to the first element. But that's not the purposed of :first-child. The intent is to select the first child of the parent.
To get around this I initially had to arbitrarily set first: in several different components. This got messy, so I eventually changed my architecture to avoid needing to select the first child.
Difficult maintenance
Another issue is consistency. If you want the same styles on two different elements you have to copy and paste the whole class list. If you want variations, and then to change them later, you're doing a lot of find and replacing. I've only created one Tailwind project, but the thought of maintaining one is terrifying.
I can already hear the feedback "make it a component". Really? I need to rig up a whole React component for what could be a single CSS class? That, to me, is insanity.
My conclusion for Tailwind is that, sure a smattering of utility classes is ok, but only utility classes as a paradigm is broken. Also, culturally, sticking to that paradigm leads to bad practices.
Worry 2: What packages do I need to do things?
So this one was a nightmare. I happened to start at a bad time. React 19 and Next 15 are both pretty new, so the ecosystem hadnt had time to catch up.
I wanted to use P5, but it didnt have an updated package. I knew Pixi had a React specific package @pixi/react. Luckily that has a beta available for React 19.
Related to this is how I found out that Pixi has a beta. At various points in the project I was searching "how to X in React 19 Next 15", and very little came back. In fairness, again, this was a new version so there might not be a lot of content out there.
What was striking though was that old examples wouldnt work. Samples of code for Next 14 are just broken in Next 15.
I find this crazy. 15 versions in, and the paradigms are still changing that much that a lot of the old basics are redundant now?
This makes me very happy, thinking of the Svelte eco system. I think Svelte 5 still supports Svelte 3. You can mix and match. "BUT SVELTE HAS A COMPILER". Yeah, and so does every realistic way of working with React.
Community
The React based communities I visited were very helpful though. Especially the Pixi Discord.
Part of me wonders though if the React community is so large and vocal because of these issues with packages. They've had to deal with so many paradigm shifts, then need to band together.
Maybe Svelte and Vue need ruin the syntax more to bring people together.
Worry 3: JSX. Just uggggghhhhhhh.
Actually, this is one I was quite ok with.
I dont love the syntax. I find it messy and very jarring with standard JavaScript, but it works.
EG
return (
boolean && <Component>
}
That's a trick. And it works. But it requires a decent amount of knowledge, knowledge that doesnt relate to templating. Dont even get me started on returning ().
"What would be better?", fair questions. I'm not standards creator, but what about something like:
return `
?{boolean}
<Component />
?{/}
`
The idea being ${} is for execution, but ?{} would be for evaluation, and ?{/} denotes the end of what is at stake within that evaluation?
There's talk of brining JSX into the browser as a standard. I'm less horrified by that now. That said, I think there has to be a neater way of achieving it.
Moving away from standards
There's a common refrain by React devs that "it's just Javascript ™".
That's right and wrong, in two ways.
Yes, it is just JavaScript, that's right. It's ONLY JavaScript, no HTML, CSS, SVG etc.
It also isnt "just" JavaScript. It's JavaScript in the context of React. For example events arent simple browser events, they're synthetic events, and you need to get the nativeEvent back from it. I'm sure there are "reasons", but I never saw a benefit to them.
The lifecycle loop of React is also so awkward and brittle. useRef, useState, useEffect. God forbid you have an issue with these. Most places React devs only respond with the url https://react.dev/reference/rules/rules-of-hooks, not helping the reader learn more. In fairness, this was rare, but there seems to be a culture of not helping explain these kinds of issues.
Transfer of skills
This and other small changes mean that a lot of my existing knowledge doesnt work in React-land. That's true of Svelte too. As percentages though, I would say React feels like 40-50% standards based, and Svelte feels 90-95% standards based.
I believe a Svelte developers skillset is significantly more transferable to other situations than a React developer.
Mental burden
The other way to look at this is that React at best, to me, only 50% feels like I'm working with the web platform.
BUT it's still being built for the web. So the mental lifting needed to make something work in React, while also thinking about how it works for the web is simply bigger than with other frameworks.
Conclusion
This was all a bit scattershot, because I could write so much more about any of these issues, and I wanted to keep things more succinct.
Overall I believe React devs would be amazed to see how much easier and lighter it is so write applications in other frameworks. Maybe that's one of the reasons they're so slow to move. They already carry so much mental weight. And each update is so heavy too. I'd be slow to try and add the weight of another framework too.