1. 32

  2. 22

    I was a die hard react fan & user for at least 5 years, loved hooks (even useEffect) when they dropped, it really felt like it was only improving.

    But recently in the last year i started at a new company with no one else having front end experience, i wrote a project in react & onboarded a few coworkers. During that onboarding i was forced to try to explain the fundamentals of react & my respect for react couldn’t withstand that criticism, useEffect is truly a horrid experience that ive just put up with & still get wrong along with all the friends useCallback etc. react context is unfinished, data fetching feels wrong, styles are a mess.

    I re evaluated the options & the next much bigger project we chose svelte & it was the best decision. What surprised me about svelte was that so often I forget im using a framework, there are footguns but they are rare enough that most the time im just programming JavaScript & it works. That feeling is completely absent in react.

    I’m not even that much of a svelte fanatic, but I’m sold on low boilerplate compiler frameworks. I think svelte is still just an intermediate step towards highly productive frontend experience, there’s still so much we need to go. But you don’t see much of it if you’re not willing to step outside the react bubble.

    1. 10

      Probably even bigger shock than what i said was, i bought that react’s boilerplate & “strictness” would prevent more bugs than a framework like svelte. In my experience its been completely opposite, boilerplate obscures logic bugs & makes it easy to miss the important details all the time

      1. 1

        useEffect is truly a horrid experience that ive just put up with & still get wrong

        Yeah I really dislike useEffect. But there seems to be no avoiding it.

        I do prefer where we are now to the awful (and fortunately short-lived) trend of render props - but that came from the community IIRC, not the React team.

        Some of the new hooks like useSyncExternalStore just make me shudder, too. Time-slicing, concurrent rendering? Why did these performance optimisations have to leak out into the high-level library interface (apparently we need a new hook that plays well with them). I have to agree with a recent commenter on HN who said that React’s focus on performance has lead to an overly complex system, when performance of the React library wasn’t a genuine issue for most people (it’s almost always dwarfed by, eg, network latency) that couldn’t be solved a little effort (eg componentShouldUpdate).

        One thing I would like to know about Svelte, Solid, etc - do they produce JS that’s reasonable to step through in a browser debugger? That’s something I’d like to get back.

        1. 2

          I haven’t tried the debugger yet, but the sourcemap works fine afaik in the dev server.

          Svelte avoids the useEffect for majority of usecases because the script is a constructor, not a render function, so you’re fine to fetch data in there. Other than that, it has a syntax for doing “effects” that run when state changes with the $ syntax.

          And better yet, the compiler determines the “dependency array” so you can’t get it wrong.

          You don’t need useCallback because functions aren’t redefined every render.

          When you start to question the assumptions react is built on, you can do a lot.

          1. 2

            Interesting. Right now I am looking at one React’s unhelpful “too many renders” errors, which has a stack trace that doesn’t help me at all because it’s entirely React internals. So I guess I will just try to reason about the problem rather than interactively debugging it like I should be able to.

      2. 9

        I was once a big React fan but have grown to resent it, for many of the reasons highlighted here. A frustrating trend is the tendency for projects to “just use React” both when React is too much and when it’s not enough. The former is an obvious and well known thing: the dumb CRUD app that could have been a bunch of forms in Rails or Django or Go templates or whatever but someone had the bright idea to bring in React from day 1 “in case we need it later,” because if you want any client-side interactivity at all in your dumb CRUD app you better believe we’re gonna bring in all of React to do it.

        The latter phenomenon is slightly newer and IMO more insidious. In the earlier days of React, devs took “it’s just a view layer” to heart, which is how we got things like Flux, Redux, MobX etc. and it was nearly unthinkable to build a significant React app without them. Then Hooks came and changed all of that. The React community went absolutely bananas for Hooks when they first came out. I myself gleefully cheerled for them in these very pages. While the core idea I expressed in that post remains powerful and exciting, I found the reality to be a lot more messy. The big meme of those days was “useReducer and useContext replace Redux! Build your own state containers! Throw out your clunky action creators! Who needs middleware when you can useEffect!!” This was a bad idea. We created just as much boilerplate to rig our DIY state frameworks together, different teams implemented them in slightly incompatible ways, and lord help you when you decided you wanted to dispatch a side effect from a useReducer.

        The breaking point for me was at $FORMER_EMPLOYER when I watched several junior teammates make tons of mistakes on our shiny new React frontend. None of it was their fault! There were tons of footguns lurking everywhere related to hooks (well beyond the basic “rules of hooks”) and our bespoke state frameworks built on them; changes that should have been trivial required large replumbings to implement correctly, and in review after review I had to explain why the code was incorrect, but it’s not your fault for not understanding that, because you see with hooks you have to shift your whole mental model, and… I felt like a crazy person trying to explain all of this bullshit to people who hadn’t drank the React koolaid. I tried to think about it like an outsider and quickly realized it all sounds ridiculous! And don’t even get me started on suspense/concurrent mode.

        I’ve since left professional frontend development, but If I’m ever faced with a project big enough to want something like React, I’ll probably reach for Svelte or Vue instead. If React is non-negotiable, I’m going to use Redux from the get-go. Unlike React itself, it seems like they’ve really been improving their developer experience. As for my next personal project, I’ll be using Go templates and htmx, maybe pulling in something like Alpine if and when I need it.

        1. 4

          A frustrating trend is the tendency for projects to “just use React” both when React is too much and when it’s not enough.

          Tom MacWright has a post somewhere in which he says that React is best for medium performance things: if performance doesn’t matter, you can just use innerHTML = whatever. If performance does matter (e.g. making a map application, like him), React is not fast enough and you need to handle canvas updates or whatever yourself. I think React hits the sweet spot for a lot of applications, but it’s not really state of the art anymore, and it never made sense for things like pages where you want good FCP.

          As for my next personal project, I’ll be using Go templates and htmx, maybe pulling in something like Alpine if and when I need it.

          I’ve been running a news site with Hugo + Alpine and happy with that combination.

        2. 6

          Not mentioned: concurrent mode seems like a weird detour that doesn’t help most developers.

          1. 5

            What a refreshingly detailed and nuanced article. My own progress through front-end frameworks over the last 11 years went something like: YUI 3, Angular.js, React, and finally Vue. I still tinker with React if only to stay familiar with the de facto standard framework. As to the question of why it is so, I suspect there are a couple of causes at work:

            1. The term “framework fatigue,” popularized by the 2015 article, A JS framework on every table, accurately described peak framework churn. It ended with the question, “Is this forever?,” to which the reaction was a collective gulp and simultaneous sobering.
            2. React came along just as large organizations were beginning to adopt JavaScript frameworks for wide-scale use. There is no better way for a technology to become an entrenched incumbent than to gain the inertia that comes with proliferation.

            It was at about that time that my company chose Vue. Looking back, I think we made a good choice. It’s been easy to use, reliable, performant, and had only one major footgun. Six years ago, React and Vue were comparable in performance, with slightly faster startup times from React and slightly faster reactivity from Vue. We lucked into what is now a huge performance differential, which seems to have been buoyed by its observer-based reactivity model that lent itself to optimization more than React’s diffing and reconciliation. I wonder if React 18’s new suspense and concurrency features are really just performance workarounds for an architecture that is fundamentally slower than its alternatives.

            Our sole cause for regret is that we picked a distant second in the framework popularity contest. This made recruiting a challenge and retention a concern. As we evaluated the migration to Vue 3, we asked ourselves if this was the time to join the rest of the herd and use React instead. The answer was a surprisingly unanimous, “No,” even from recent hires who knew only React prior to joining us. Although Vue 3’s composition API looks a lot React’s hooks (which, like others here, I consider to be needlessly complicated footguns), Pinia relieves us of having to use them in most cases. And whereas Pinia is a simpler, faster evolution of Vuex (merging actions with mutations and adding support for caching in getters), Redux seems to have gotten only more complex and confusing over the years.

            Mileage varies, of course. A big question worth considering is whether a given project needs server-side rendering (SSR). Our bread and butter is WebGL apps. We do render WebGL assets server-side for some situations, but doing so is slow and expensive, so using an SSR framework like Nuxt to render the entire app server-side is out of the question. But for many other projects, SSR is likely going to be a high priority, and I suspect the ideal architecture from a performance standpoint has to be something better than rendering the initial page state on the server and shipping the entire app to the client for subsequent updates. There are some intriguing alternatives like HTML-over-the-wire frameworks (e.g. Phoenix), the islands concept in Fresh, or the resumability concept in Qwik. The kid in me is very excited by all of these ideas.

            1. 4

              When and how does this change? … I don’t have an answer.

              …come on, it’s the same Wheel Of Tech Reincarnation that has been rolling for 25 (or 75) years. React will stop being mainstream when one of the following occurs:

              • Something new and revolutionary(ish) happens and is good enough it becomes the new buzzword (like Rust did)
              • A new hot company becomes the one everyone wants to imitate and points to a particular tool for its success (like Angular and MongoDB did)
              • A new generation of programmers grows up and starts working in the problem domain and they have new ideas and ideals and can see the possibility for something better instead of being used to the way things are (like Go did)

              Please don’t nitpick the examples, they’re subjective. There’s also more possibilities I haven’t listed, I’m sure.

              1. 2

                A new hot company becomes the one everyone wants to imitate and points to a particular tool for its success (like Angular and MongoDB did)

                Which company are you referring to here, please? I think this bit of history passed me by.

              2. 4

                I have enough familiarity with React to be able to navigate a codebase written in it and do basic things.

                But I have a lot of experience with Django, which in the Python world comes in for the same criticism: why is it so popular when it’s not the absolute best at any of the particular things it does? This was a big argument once upon a time (less so now that the ecosystem is more settled-down, but stil heard in some quarters): Django’s ORM isn’t the best ORM, its template system isn’t the best template system, etc., so why was Django so popular? And why is it still one of the top Python frameworks now, over 16 years later? Surely one of those other objectively-better things should have out-competed it by now!

                The answer I have for the case of Django is long and complicated, but it boils down to: evaluation of a framework requires more than just evaluating particular aspects of it completely in a vacuum and then summing the scores. In Django’s case the ease of having the full stack well-integrated and well-documented, versus the other “pick what you think is the best component in each area and glue them together” frameworks, was a huge factor, as was the ease with which Django’s “app” concept encouraged a whole third-party ecosystem of nearly plug-and-play add-on code. Effectively: something that’s just a well-integrated bundle of acceptably-good components can easily win over something that tries to pull in objectively-best bits but stumbles on the integration, or has to trade off being below average on one component in order to be far above average on another.

                Or maybe the simplest analogy is like going to a chain restaurant: you certainly could find better food somwhere else, but the chain has a known, consistent level of quality and saves you the effort of hunting over listings and reviews to try to find the “best” when you’re hungry.

                And I think React is in a similar position: sure, you can isolate some particular part and say another framework has a better version or better approach to that specific thing. But it’s very hard to find any framework that does better on all the things React does, and you know you’re getting a certain acceptable baseline out of it. So it wins.

                1. 4

                  Any post criticizing JSX is one I can get behind. It’s one of my least favorite trends that caught on for what feels like the wrong reasons.

                  I feel React’s history is still important. It played a vital part in mainstreaming declarative, functionas styles of programming. My personal career would have gone nowhere without React boosting adjacent ideas.

                  1. 8

                    I like the theory of JSX: let’s take XML-ish and inline it because (X|HT|SG)ML turns out to be a pretty good document markup language. The practice stinks though because it’s just pointlessly different than HTML in arbitrary ways, and the syntax for looping and conditionals is tedious to type. Plus it’s preprocessor, which invites problems. The Lit HTML approach makes more sense now that we had backtick template functions in JavaScript.

                    1. 3

                      It’s not just that though. JSX compiles down to something incredibly simple in theory: trinary functions (string element name, object of attributes, and array of child elements). This isn’t complex but JSX adds a ton of complexity to do the same thing—the only part that sucks is that JavaScript, not being a functional language, the ergonomic are terrible, impossible to read. You look at ClojureScript, PureScript, Elm, and the API is pretty much this but legible like Pug.

                      1. 4

                        I can’t think of a time where I ran into an actual issue and JSX was the culprit though. In theory, it’s weird and I don’t love it. But in practice, it’s been totally fine.

                        Now, JS not being a functional language, that I think is a huge issue. That’s why React and Redux have always been less than ideal. Hooks are weird! They have a great API, but they rely on global mutable state, which at the end of the day there’s no getting away from in React. It’s really not as stateless as they claim.

                  2. 3

                    Meta-point: The hype cycle is laughable at this point.

                    3 years ago I worked on a full-rewrite of a large frontend to React. At the time, the argument from leadership was “React is the most popular now, and it will be hard to recruit new devs if we’re not using it.”

                    Guess they’ll be rewriting the whole FE again next year.

                    1. 3

                      I’d argue that this article is good evidence of the hype cycle having slowed down, if anything. React has been the dominant Javascript UI library for more than half a decade at this point.

                      1. 1

                        “half a decade” for a tool that you have to base your business on isn’t a good thing.

                      2. 2

                        React will be the dominant framework for at least the next few years, and will be with us for the foreseeable future. Facebook’s providing the resources, and there’s a professional ecosystem around it (NextJS / Remix / Astro, MUI / Chakra / Ant, Redux / Tanstack) that isn’t rivalled by any other UI library.

                      3. 3

                        If anyone could afford an extra few weeks for the learning curve for you or your team, what framework would you use on a greenfield project or new web app instead of react? Or would you just go with preact?

                        1. 3

                          Last time I had to make a web interface svelte was easy to pick up by pasting code samples and seemed pleasant.

                          1. 1

                            Oh I forgot about svelte. I wonder if react contributors could implement the react api against a no-virtual dom also.

                        2. 3

                          I was surprised to not see any mention of React Native. Being able to share significant amounts of code between our web app and our Android and iOS apps is a major reason why the frontend folks on my team choose to stick with React. (I’m a backend guy so I have no horse in this race, but I’ve been in the room when this exact topic was discussed.)

                          1. 1

                            yes, this is in my view, a major reason of React’s popularity – the native mobile development that enables developers to write (not all but a lot) of their code in a way that it runs on web (react-native-web), and then Android, IOS, even Windows (via react-native).

                            I have heard more than one person speak well of Svelte, but I have not had a chance to look at it, and the system I am working on is heavy on React Native.

                          2. 2

                            The learning curve point was very poignant for me. I’m dealing with a project at work where the maintainers don’t know anything about React lifecycles (or much JS at all) and so there are footguns everywhere with setState getting called in the wrong condition and causing infinite loops. Or how they use this.state for everything even if it’s not rendered because that’s what examples would lead you to believe, so they ignore the “don’t modify state directly” lints everywhere.

                            I used to like React before this project, but now I see how much is relying on convention rather than enforced by the framework.

                            1. 2

                              I have to say, this fulfills that classic stereotype of the JavaScript developer always seeking newer and better frameworks, as if framework churn wasn’t a problem in this ecosystem.

                              React has aged.

                              Initially released 9 years ago as of this writing, and still maintained! Hey, it might actually be stable enough to consider using!

                              Safe bets don’t pay off big.

                              … and risky bets usually come with a huge cost? But yeah, not my problem. By the time [new risky framework] dies, someone else will be maintaining the codebase, and it’ll be their problem. Because I’ve quit my job and moved on to the next company where I’ll keep playing with risky new frameworks.

                              Stability, reliability, longevity, sustainability… these are undervalued in today’s world. Nobody thinks about what will happen when the risky crap eventually hits the fan, and it’s usually our successors (or children and grandchildren) who experience the consequences.

                              We try to predict too much what technologies are going to stick around. The key to choosing a stable, reliable technology is not to try to predict the future; the key is to look at the past. If a framework has been around for a while, it’s much more likely to stay around for a bit longer.

                              1. 1

                                Most frontend are rewritten every few years when trends change. Why predict anything when it’s all disposable anyway?

                                1. 1

                                  That’s another really important part of my point. Something is seriously wrong if you need to keep rewriting your software every few years. IMO, instead of building disposable software, we should be building maintainable software.

                              2. 1

                                I have to agree with the general thrust of this article even if I disagree with or don’t understand some of the criticism (especially scalability - what does that even mean for code that runs in the browser?). Most of the changes to React since even before hooks don’t seem to have improved the library very much, and as others have mentioned, hooks was probably a downgrade from lifecycle methods in terms of the number of footguns it introduces.

                                My guess as to why React is still dominant is that there just hasn’t been the kind of improvement that would cause software developers to wholesale ditch React for something new, yet.

                                1. 1

                                  especially scalability - what does that even mean for code that runs in the browser?

                                  In my experience, the big one is that as your application’s LoC count grows (as you add more screens, routes and feature), you run into some problems that scale up with total code size. Those in turn have mitigations, but the mitigations themselves also have costs.

                                2. 1

                                  One obvious reason that people still choose React but which (AFAICT) isn’t being mentioned is exactly that it is so popular and widespread. Choosing React may well cause some of the undoubted problems in the article, but it also means that as long as people writing sites or apps with it conform to some basic and fairly well-established conventions, it’s going to be significantly easier to hire someone to replace them when they inevitably move off to use some other cool new framework than it would be if they’d used some cool new framework that no-one else yet knew and which they chose before it was cool so that they could show how ahead-of-cool they were. On top of that, simply sticking to those basic conventions is going to mean that the people they leave behind aren’t going to be cursing them after they’ve gone for having left a bunch of unmaintainable code relying on some now-shuttered off-stream alternative.