I get the impression that React is trying hard to catch up with the more modern, easier, faster and cheaper alternatives. But instead of fixing the root problems (rerendering and often required memoization, leaky abstractions) and make React easier, it becomes more complex.
If the end result was great, I would understand all the effort. But it isn't. React is even slower in real world than the benchmarks show. Next is even worth. I've seen recently many dog slow websites built with Next.
Really, I don't get. If the React team wants to improve React they should fix the core.
The ecosystem has too many dependencies that break at this point. Consider that Target.com, Walmart.com, Microsoft Teams, and untold masses of sites are React.
The huge component ecosystem.
Entire companies built around it.
The core concept is broken§, but fixing it means possibly breaking everything else. If you're going to break everything, might as well use something else.
All we can do is truck along at this point; stuck with React because of the mass of the dependencies.
§ React is the only library/framework that is opt-out of re-render while Vue, Solid, Preact, Svelte are all opt-in. This is one of the core reasons it's hard to do right and prone to a specific class of bugs that rarely -- if ever -- show up in other frameworks as you constantly have to be aware of opting out, even in what seems like normal JavaScript.
The `<Person />` component will redraw on each `increment`. Nothing changed. Why would it redraw? Because when the `App` component redraws, the `einstein` variable points to a new reference. React sees this as a change and redraws both `App` and `Person`. What looks like normal JavaScript here is not. To prevent this redraw, you have to opt out like this:
Or know to move the reference outside of the `App` like this:
const einstein = { firstName: "Albert", lastName: "Einstein" };
function App (props) {
...
}
Which is fine in this case because there are no dependencies on the component tree. This is the most common mistake I see in React that leads to bugs. It's not just objects, but also functions.
Why? Because on increment, the `logConsole` is a reference to a new function. So the `Logger` redraws as well. So here, you need to opt out once again by using `useCallback` or moving the function out of the component tree (fine in this case since there are no dependencies). The thing is that it looks like normal JavaScript but the React render cycle is the unseen; you have to be aware of moving things "out of the way" and "bringing them back" via a hook.
React's render cycle re-evaluates entire component sub-trees for changes and if your component doesn't explicitly opt-out by preserving referential equality (`useState`, `useCallback`, `useMemo`, etc.), you'll trigger a redraw downstream. These hooks effectively move the references out of the component tree and pull them back in when the tree re-renders and thus preserve referential equality.
So what teams might do is after experiencing this one time chasing down a bug is wrap every single declaration in a hook to reduce the mental burden. This then creates other issues like performance and memory.
Vue, for example, is the opposite because it has fine-grained reactivity. Nothing redraws until you opt in by using the Vue reactivity primitives.
After all this time, React's sheer tonnage of boilerplate still astonishes me. That abstraction leaks like useMemo(…) even need to exist in the first place…
Folks want to solve their own problems, but they keep getting saddled with React's as well.
Evan You (creator of Vue) had a great quote on this:
> The pain and suffering of hooks all roots from the mismatch between a dogmatic belief in the superiority of immutability and the harsh reality of the host language that is JavaScript (Feb 25, 2023)
This fundamental misalignment with React and JavaScript is the billion dollar mistake.
Nah, I still think React made the right choice. I used to use functional languages so coming to the JS world and seeing that no lessons from that world were learned was disheartening. React, where UI = f(state), is an amazing model compared to the imperative jQuery model of before.
Sure it does, it is good because it's functional. I could similarly write a convoluted yet highly short Perl expression, less code is not always better.
I tried Solid. Signals are not new, I've used Knockout before and it turns into a spaghetti mess after a few years. I guess people today simply aren't old enough or experienced enough to know what eventually happens with fine grained reactivity.
That page doesn't really answer why it can solve the issues of Knockout better. Eventually the same problems will arise, of spaghetti code among things reacting to other things reacting to yet more things.
Well yeah, it's the difference between understanding structural equality and referential equality. I always got the sense that people who can't figure out why things rerender when simply never took any classes in college on the difference (which is likely true since many bootcamp devs don't take such classes, and the vast majority of them learn the MERN stack).
The reason I moved away from Vue is precisely due to the spaghetti nature of fine-grained reactivity. It's like people learned nothing from the reactive stream days during Knockout JS. In a big enough app, the state simply becomes unwieldy and I am always grateful for the unidirectional dataflow and explicit setting of data in React.
UI = f(state), and that's how it should be. useState and other hooks seek to keep state around since at the end of the day we need to make components that perform functionality, and it really reminds me of monads in functional programming. Coming from such FP languages, React was and still is a great paradigm.
You bet. But if you grok that simple example, you can see why teams that switch to Svelte, Solid, Preact, or Vue feel "refreshed". This mental burden of trying to figure out what has to be put where just...goes away. The React model tries to bend JavaScript to conform to it's render cycle rather than designing to JavaScript's unique object-functional strengths.
Thanks. A while ago I sensed the churn dangerzone around React and I refused to get on any React projects. I feel lucky that I had that option. I did some Angular projects (i think it was version 8-9) and to me it seemed okay at the time. The project evolved nicely and structurally it organized itself quite well. But there is a ton of boiler plate there as well and I’d avoid Angular in the future.
Im doing mostly back-end work these days to keep my sanity.
I admire parts of Angular's vision and think there are patterns where it shines, but it's never quite felt like they actually hit 2.0 to me. I haven't worked with it in a few versions, but I think it's just a different set of complexities.
There's always some big or missing thing right around the corner... reworking Material components for years, reworking internationalization, improvements to reactive forms, zoneless Angular, single file components, etc. And, for as many bugs as they fight down, it's always felt like there were several obvious frustrations waiting to be fixed. It's all just left me with an impression that the team bit off more than they could chew in creating such a holistic solution and can't quite get to something solid, hence the need to shed things like Protractor.
Hopefully the cumulative effort to improve gets them somewhere and helps get Angular into a more complete and compelling place for folks.
If Angular wasnt based on RXJS, I would agree with you that the defined structure of Angular makes it nice and predictable. RXJS pipe hell is a hell I wouldnt want to send my worst enemies to.
If the end result was great, I would understand all the effort. But it isn't. React is even slower in real world than the benchmarks show. Next is even worth. I've seen recently many dog slow websites built with Next.
Really, I don't get. If the React team wants to improve React they should fix the core.