The past two years there has been a growing dissatisfaction towards React. You can find people trying to find arguments against choosing React. I've done that too, because there are some severe issues in how we use (or don't use) React. Mostly the issues have to do with stuff like performance, search engine optimization, accessibility. It is easy to point your finger to what appears to be the "root of all evil", React.
So what are the problems with React and are there any ways we could deal with them?
"React becomes messy in large applications"
The above is one of the statements which I could agree on, but not without conditions. Because the real problem here is not really React in itself!
The biggest thing one can argue against React is how it puts HTML and DOM away from sight. When looking at JSX you don't really see that much of clean HTML structure by looking at all the combinations of components. This means that to have good HTML you really have to have good component level abstraction which would allow pretty much any developer to produce mostly good semantic HTML with minimal effort. Or you'd have to setup tooling that validates HTML, and aggresively encourage using browser devtools with focus on the HTML.
And these things are a problem. First one requires there to be at least one developer who builds good component abstractions so other could just focus on building a good app. Second one means you need somebody to be aware of the need in the first place, and the time to do that and actively advocate.
To me it seems neither of the above really happens. Instead you have a lot of projects where people have chosen React because that is what everybody is using, yet the teams consist more of generalist programmers rather than many who have high HTML, CSS, web standards knowledge.
And once we have this kind of a team: how likely you think it is that they choose the best additional libraries to use? I'll throw one example that probably shouldn't have caught as much popularity as it has: CSS-in-JS.
Why I say this? Well, it limits even further the visibility and knowledge of web standards, in this case CSS. You're unlikely to learn much of CSS selector usage with CSS-in-JS, mostly you deal with just pretty basic styling. CSS-in-JS also encourages "duct tape" type of components, so when discipline is missing instead of having a good set of base components you end up with lots of style utility components.
This kind of embracing React and JavaScript, and sort of an "elimination of web standards" from direct visibility is likely a reason why many new front-end developers working at companies have quite a challenge creating good usable, accessible components with semantic HTML, and robust CSS. The written code doesn't embrace them and the only way you gain the knowledge is by knowing to research, likely requiring one to spend their free time to learn, or by having a mentor who knows the web well.
"React is bad for thing X"
You have HTML mostly out of sight because JSX, and focus being on components. You have CSS mostly out of sight because CSS-in-JS. You have everything controlled via JavaScript.
A truly wonderful thing about HTML is how fast browsers can process it. And the same goes for CSS. The traditional wisdom has been to have as little JavaScript as possible. We used to only enrich HTML progressively with JS.
With React this has turned upside down. One of the reasons for this is how we use React. We probably render the entire page with React on server side. Then we also take control of the whole client DOM tree with React. This means the whole page is being taken over by JavaScript.
To workaround performance issues we have thought to do intelligent code splitting, so bundles per page could be smaller. The typical end result to this is pages with something like 20+ JS bundles being loaded on first page load. Because we also thought prefetching improves performance for the next page load.
We now have tools like Lighthouse and Web Vitals to measure how this kind of setup performs, and well, it ain't pretty. It is very hard to optimize when React takes over the entire DOM.
There are also other issues with React taking over the entire DOM. A typical example is growth hacking. While I don't really like the whole concept and the current way it is being done with A/B testing that needs months of time to see any results, it is still a thing that exists and companies seem to like to do it. And the challenge here is that you need to provide places for external scripts to hook into your page. This easily gets into conflict with React having made to have the entire DOM for itself!
Growth hacking is not the only case. People may use Google Translate, or other localization tools. React controlled sites tend to break pretty bad and become unusable. For a business this can mean lost sales.
Fixing the process
For companies with a continuous project there are a couple of things they can do to help avoid these issues from piling up. One possibility is to hire more of your own developers, and aim for having people working on your projects for longer. Give them time to learn alongside work, maybe arrange mentorship, ensure you have some devs with longer experience, and especially people who are passionate specifically about the web. Prioritize your business needs so that there aren't too many big features needing to be done at the same time.
I think all of these are very hard and not many companies can confidently cross all the boxes. Of course consultants can work fine as well, but it is harder to guarantee their longevity in a project. Many consultancy companies seem to favor rotation to ensure satisfaction with new challenges every now and then.
As for developer level one of the things is to reconsider the way React apps are written: maybe you don't need to wrap the entire HTML everywhere. Maybe you can have "widgets" instead: load React miniapp for specific feature as needed. So even if you render the whole page with React on server side, you could abandon most of universality, as that will guarantee you don't need to hydrate the entire DOM tree with React in one go. This is a very possible scenario for sites that have content focus.
Of course this kind of change is hard to accomplish. Some of you may use React frameworks like Gatsby or Next.js. So far I haven't had a look whether these frameworks can be customized this much; probably not. Luckily there is a new player on town that lets you have only as much JS as you need: Remix. It is still in beta, but it encourages existing web standards a lot more than other solutions. In the other hand it does cost money, so that can be a blocker for new devs.
Use the web standards
As conclusion React is a valuable tool and we get stuff done with it. The problems we may have with it is in the way we use it, often due to ignoring cost of hydrating and controlling the entire DOM tree on client browser, and in the other hand by encouraging coding where JavaScript is made to control everything.
To cure this: embrace HTML and CSS over JS (when it makes sense). Front-end facing code should reflect more that you're working with HTML and CSS. Accomplishing this is not an easy task, and I don't yet know how to actually successfully shift code so that even though you'd be using React, you would also bring HTML and CSS in as first-class citizens. So that even the new devs working with the code would get the idea of what is important on the browser side, that it wouldn't get lost in all the code even on a larger project.
A possible issue here is that we're breaking the "universality" of having the exact same code executing on client and server.
I guess splitting to two parts may feel like we might be doing "double the work", but I think that might be an illusion. Often the features we do for browser side are very front-end only. Some things like checkouts might not even make much sense to have with server side rendering.
But I don't know. How do you feel about React codebases that you face every day? Does it seem like HTML and CSS is obvious to you, or is it out of your face? If someone with less experience had a look at the code would web standards be obvious to them? Do your tests reflect that, indeed, you are really outputting HTML? Do the tests include accessibility checks? HTML validation? Is the code rich on a variety of HTML elements, or do you only have a bunch of divs and spans? Does the JavaScript code rely on native browser features, or are existing browser features rather mimicked by JS?
At least I miss many of these on my everyday project at work.
Top comments (6)
Just to let you know that I love my React code, they are super clean and concise. JSX, css, js... all go along together nicely. Cheers
That is great for you! Although in general I'm more worried about the output than the input.
Clean code is pretty relative: you can have code that looks pretty and understandable looking at it, but it may behave suboptimally. React has (at least) two major suboptimal solutions behind the background: virtual DOM, and memoize-reliant hooks. Both consume memory and CPU time to provide a better developer experience. This is one price you pay to achieve a clean and concise when writing React, and you can't workaround them as everything is based on those two solutions.
And for most projects this is totally OK.
So you are the kind of developer who would sacrifice code readability for performance. Performance is cheap these days, and my apps never struggle in that category. Code quality, however, is something that most people can never achieve no matter how much they try.
BTW, Hooks sucks, same for Redux, or Styled Components. If you fall for them, no wonder you hate React
No, I don't sacrifice code readability. Also, I'm wondering where you get the "hate React" part as I'm just being critical and analyzing causes for issues, avoiding to blame it on only React. As additional background I've worked on high traffic ecommerce sites, with React since 2014.
Your apps might not struggle, but looking at the web as a whole there is a lot to improve on size, first execution perf, a11y, and so on. And I've seen what seemingly simple and small looking improvements can do to a site's success. What is truly hard is to make other devs "not mess it up" over time. Code quality alone doesn't help, you need tests, and likely teaching and documentation, and a fitting culture.
React community is pretty split now on what people prefer. Others believe everyone is using hooks now, and some go all-in refactoring everything to just hooks. Some people even believe the only thing you get support for from the community is for hooks! Then, as you know of yourself, others keep on using classes and hookless function components. I just use everything balancing for best fit on a per case basis. Of course to get there I did have to write and refactor a lot to hooks to see the good points and pain points.
Styled Components is awful and wouldn't have ever made use of it, but didn't get to do that choice on what I'm working on right now. After summer vacation I'll put the best show I can to convince the team to start a change away from it.
What would you use to quit Styled Components ?
Likely anything that allows for automatical scoping and is zero runtime. CSS Modules possibly, or Linaria if people prefer having styled-like syntax. Personally I'd be fine even with a more traditional SCSS approach, but people don't really handle grooming CSS, and many have challenges to understand conventions like BEM. Scoping makes things a lot easier for most.
For me the major weakness with Styled Components is how much it encourages to do dynamic runtime styling with JavaScript, and because people don't always think what they're doing they add in things like
react-spring
which I guess feels natural to use: each time I've seen SC I've also seen some spring library added in as well. The problem is springs are for complex animations, but in the actual apps all the real use cases only needed simple two state transitions (such as accordion closed, accordion open). Total overkill to add JS to control the entire animation. Controlling the boolean state is enough.