552 comments

[ 0.69 ms ] story [ 321 ms ] thread
"frontend engineers"
same as "backend engineers", "database engineers" or "ai engineers" or "data scientists"

we are all just primates staring at blinking lights and poking things

Yep! I’m full stack and have no clue why some people want to say frontend engineering is “less than” backend. It’s all a means to an end. The product requires both sides equally in most cases, and neither side is trivial.
If anything, what I miss from doing "backend" is the ability to just pull in whatever library I want to solve a problem.

I need a web server to work by slapping together fifteen Java libraries from thirteen different code houses and writing an absolute Shoggoth of shim code to convert between their types and classes? Sure, whatever, datacenter storage is damn near free.

I need to put code on a client machine on the internet? You'd best pick one of these date libraries, because there's no way in hell we're justifying shipping moment and Joda down the wire.

Somewhat ironically, the absolute worst engineers I’ve ever worked with are the ones that look down on frontend as a lesser discipline.
What context am I missing to interpret this comment?
You've had this account for over a decade and this, a childish display of junior capability, is the pinnacle of your contributions.
That is honestly hilarious, I took a look at their other comment (singular), and this person waited literally over ten years just to post this comment. Wow.
The post is excellent (and I actually got quoted in there from my "Rendering Behavior" article), but the title seems completely over-editorialized? There's not even a mention of the word "fractal" in the post.
We've reverted the title now, in keeping with the site guideline: "Please use the original title, unless it is misleading or linkbait; don't editorialize." (https://news.ycombinator.com/newsguidelines.html)

(Submitted title was "React is a fractal of bad design")

It's exciting & unsurprising to me that state is such an unsolved problem.

For the longest time React was kind of in denial to a large degree about what they were. They called themselves a View library. Hooks have definitely noticeably changed that relationship, & how people integrate app state with React, but the problem here of updating hasn't really changed all that much.

It's not a new thing either. A lot of the initial resistance to React & the VDOM was that it felt like unnecessary work. Because so many frameworks at the time were working towards two-way data-binding systems, which aren't necessarily but were often associated with with smaller, precise DOM updates. HP/LG's WebOS's underlying Enyo project was one high profile would be effort here.

Signals have definitely been a good re-grouping point, for reconsidering what the shape of things might look like, for trying to do a better job.

I'm a bit surprised we're still operating so much at a library level regarding reactive systems/signals. JavaScript objects have quite a lot of flexibility already, and the addition of Proxies added a lot of capabilities. Faint/distanct memory, but I think Proxies were justification for killing Object.observe[1]: now users could do whatever they wanted, so we no longer needed a JS native way to see objects change. Yet, we're still very library based, rather than trying to make objects themselves better, more reactable.

[1] http://web.archive.org/web/20200218195131/https://developer....

There is context which wages a war against debugging and testing, for one thing.

React has no real answer to state going sideways.

Then there is controlled/uncontrolled component which is an example of structural instability (what looks like a tiny change to your boss is a bigger deal than it should be) unless you ride the crazy train and use “plain ordinary javascript” to build a parallel system to move (some of) the state around.

One of the main reasons I was so hopeful for Object.observe was because it would have been a stable language feature to build better debuggers around.

Instead, it feels like most state management libraries ultimately end of writing their own Chrome extensions. Which now that I say that makes me curious: do any of these executions also let you observe/monitor server-side state management systems?

You can often use route params or location hash for communicating state sideways if shared context is overkill, with the benefit of making the state bookmarkable or accessible in the history.
That's only sustainable for small pieces of state or some mechanism to exchange that small piece of state for a more complete piece of state.
Right, the problem with React is it has no global answer for application state, instead it provides a toolbox with which it is possible to set up your own state handling but frequently you face structural instability where a small change in your app’s functionality require large architectural changes.
> or some mechanism to exchange that small piece of state for a more complete piece of state

using links to refer to information is, like, not a totally foreign concept to the web (and certainly granted: in some cases this issue of signaling via url can get quite ugly; but often it's not).

If you are having trouble testing context, you are _definitely_ doing context wrong.

To test the context itself: pass as children of the context components to render the context state.

To test the components within the context: create a context with mock functions/values.

React has no answer to state going sideways because React manages a tree of components, and you are not supposed to connect random branches of a tree. That would completely break the concept of tree, container/contained, and just convert everything into a graph, and graphs are much harder to deal with. BTW, HTML is a tree, not a graph.

Controlled vs uncontrolled and the boss demanding a tiny change is just another case of bosses not knowing about how it works the system and imagining things and then demanding reality to conform to their imagination. Not an issue with React.

For the goals of the application you can push a button in one branch of the tree and it has an impact on many other branches…
That still means you have 3 different types of entities.

One where the event originates (knobs), one where it will gets translated into actual UX effects (DOM updates, API fetches, whatever, lets call these servos and gauges), and one place where the business logic lives that transforms between the low-voltage input signal and the high-voltage output driver power.

Without that transducer you have incompatible things.

Yes, many times this is a trivial thing, and that's usually when it can be done internally to the component.

That is one of the many partial answers that works some of the time but not all of the time.

For relatively simple applications you can push all the state high up to the root of the tree or near the root of the tree and have it flow down with props.

There is a complexity hierarchy and around the time people woke up to AJAX (there were a few years when it was just a ‘evil Microsoft thing’) I was writing apps that were highly dynamic, the extreme example is an IDE with property sheets or something like Adobe Photoshop where an arbitrary number of components need to ‘react’ when a piece of data changes. It is bad enough when there is a status bar and four other parts of the UI determined by management that need to be updated when a piece of data changes (could become five or six tomorrow). it is worse when the user can instantiate arbitrary components (say for a knowledge graph editor or a geospatial intelligence tool) that ‘listen’ to event changes.

Prior to 2010 I was building apps like that and developing special purpose frameworks to do exactly as you say in GWT, Silverlight and such. There was no support for such things at the time, no async/await, management and other devs had no idea of the ‘race conditions’ that could happen when data could either come out of a cached copy or get fetched.

In those cases I spent a while struggling to understand the problem and developed systems for handling state in complex applications so when I look at React, Vue and most of those (with the possible exception of MobX) I want to ask “where’s the beef?” because these frameworks are not adequate to the problem and people don’t seem to understand they are no adequate to the problem (it comes from Facebook, how bad can it be?)

Most of the reason why people think "React is OK" is that they are writing apps (99% of them) that are so simple they don't need React. If you're writing apps that really need React, than React doesn't seem OK.

> it is worse when the user can instantiate arbitrary components (say for a knowledge graph editor or a geospatial intelligence tool) that ‘listen’ to event changes.

Your application is effectively "anything can modify anything", which is the previous step to "anything modifies anything", I/E big ball of mud. React's answer to that is "keep all the state in a small component" (small ball of mud) or "keep the state in a tree" (one-direction bindings, prevent state graphs).

This makes React discourage (I/E makes harder and puts friction) graph-based state, as it is the most direct path to big ball of mud.

This doesn't solve your problem, but definitely helps push 99% applications away from the big ball of mud. The fact is that for your 1% case you need the big ball of mud, and, in your case, pushing away from it doesn't help.

I'll push back on that.

In those two applications I joined failing projects that really were a "big ball of mud" and got them working. I didn't just figure out a working solution to the async updating problem, I became intimately familiar with seductive non-solutions.

The problem with the discussion about React is that 99% of the use cases of React don't need to be an SPA. If it's possible to SSR your application you don't need React! Those applications I worked on were dramatically more complex than today's SPA because they needed to be SPAs!

Back in the 1990s people would define a web form in a static HTML page and then write a separate CGI script to handle the form. If there was an error in handling the form the CGI script was unable to redraw the form with an error message and the values filled in because the CGI script didn't contain the form.

Around 2000 or so people realized the answer to this was for the form to drawn by the same script as the form handler, and the script would choose to either draw the form or the next thing after the form based on the inputs it received. Ruby on Rails institutionalized this around 2005 and misappropriated the name "model-view-controller" for this.

Not long after 2010, for reasons I still don't entirely understand, the web design shops in my county transitioned from successfully writing quality RoR apps to attempting to write "simple" Angular apps. How to do error handling for forms on the server side got forgotten like the formula for Damascus steel and instead people started writing SPAs to do what would have been a trivial task in a server-side application except now the application is "a tiny pebble orbiting a supermassive black hole made out of dark matter".

People who are happy with today's SPA frameworks are happy because they are developing applications that don't need to be an SPA. Once you get into the range of applications that really need an SPA they let you down.

SPAs exist because of the developer experience and user experience, the support for complexity is an added bonus.

Everything can be done with SSR, but some things are terrible with SSR (oh, you need real-time updates? have some meta http-equiv refresh header, and observe the beauty of the page going blank and re-rendering every second).

Before you ask about the developer experience: it's about having developers that can focus their brainpower into animations and interaction design without having the expectations of having to know SQL.

4 letters. HTMX.

Or look at https://www.phoenixframework.org/ to see what a web framework would look like if real-time updates mattered. (That said I do find that simple IoT applications like a volume knob for my smart speakers in party mode or that can toggle my lights do work well with websockets + mobx + React.)

As for DX, I think waiting for "npm run start" to get out it's own way is a large enough decrement that I don't have to get into all the many problems w/ JS build systems.

I will grant that React is nice for an animation-heavy UI and I play video games enough that I appreciate such things. Another thing I like about React vs similar competitors is that the rendering model is flexible enough to enable things like react-three-fibers which is another reason for me not to invest in Vue, Svelte and things like that.

As for user experience isn't it the dark truth that Google and Facebook want "as many UI redraws as possible?" Let's face it, the honest clickthrough rate on ads is indistinguishable from zero but when you visit some site like anandtech it is by no means accidental that the layout rerenders endlessly because each rerender is a chance that a click on a link is transmogrified into a click on an ad. It's covert click fraud and is a large enough decrement and between that and the endless staring at spinners and waiting things to load any possible increment in user experience is at best hypothetical.

(e.g. in another window I have a completely SSRed app that uses HTMX. It uses zero spinners, runs as fast or faster than a desktop app, and never has the UI move around mindlessly. I grant it would be cool if it had some more animation but would I trade that for rock solid responsiveness?)

HTMX definitely chips at some of the use cases of SPAs. What percent of cases? I don't have that answer.

And yes, Phoenix is a very interesting thing, but it's most likely only viable because of it being Erlang under the hood (needs a process running for each client, hence ultra cheap Erlang processes being a good fit).

> when you visit some site like anandtech it is by no means accidental that the layout rerenders endlessly because each rerender is a chance that a click on a link is transmogrified into a click on an ad

I think you went a bit too far into the conspiracy theory there. An element for which the height is not defined (via HTML or CSS) gets rendered usually to 1x1 pixel, which forces a redraw if the element turns out later to have width and height (like an image that takes half of a second to download). Which, IMO, means web developers are not bothering to put sizes in delayed-loading elements, which points a bit more to the incompetence side than the malice side. But ads probably not specifying width and height would also indicate significant malice, can't rule that out.

the "MVC" nomenclature came from traditional desktop apps, no? RoR just followed suit.

So, I always "hated" RoR, because it was full of hidden conventions and regular black magic. At least PHP was globally simple and primitive, even if locally ugly and complex.

I still remember Misko's early(est?) Angular announcement video, it was just part of GTAC [google test automation conference], and the whole thing was about testability.

https://www.youtube.com/watch?v=gQclnI_8Vmg

It was seen as natural separation of concerns, it was seen as - finally - breaking free of the big bulky backend (of GWT and the shackles of semi-autogenerated frontend code) the frontend runs on the browser anyway, it needs to manage its own state anyway, etc, etc.

Of course this only emphasizes your point, that a good ~95% of the sites are not like this, they shouldn't even try to manage state on the frontend.

> Once you get into the range of applications that really need an SPA they let you down.

Yep. I wholeheartedly agree.

10 years with an unchanged react state model:

https://reagent-project.github.io/

Having used reagent, watching the React space evolve is like a bricklayer watching a constant stream of innovations around mud. Sure, you could build foundations with bricks, but why do that when you can use a fancy mold and pour mud into it? Why have clean blocks when you can have sticky, messy, dirty goop?

Alas, castles and fortresses have been built with messy goop, and the amount of goop-specific tools and goop slappers far outweigh the bricklayers. So I too slap goop.

Have you seen the debugging tools for goop?

I mean, they're absolutely necessary because the goop is full of insects. But so elegant!

This kind of thing is possible because the React state model ultimately hasn't evolved too much itself; only the easily-accessible user-facing parts of it.

I've been running a mobx-react setup for 7 years. It's been thru a few syntaxes but it behaves identically. Minimal rendering, observability, I find it the most intuitive state management pattern.

I missed it in the article. How do signals fix react's shortcomings? With signals you still have the same exact state management problem of having these crazy stateful functions. Sure you don't need to deal with the additional complexity brought about by use effect and rerenders but that's only a small part of the problem in my opinion.

I've gotten to the point where I think frontend code should just be modeled as state machines from the start. I like XState but you can use reducers too if you like.

Lovely read. I’ve been in TS and React land for a year now and it’s been so great but as our codebase grows I do see the walls closing in a bit. Signals are interesting, I wonder what react could look like if they supported them more natively in the library in the future.
I've been feeling the same sentiment as the author.

Having worked on 3 sizable React projects now (all started before I arrived), I can only conclude that beyond a toy phase -- once you have many hands working on React and *particularly* once you start managing sizable state -- there is only pain.

The most recent case resulted in spending quite a bit of time explaining to a peer why we were experiencing an unexpected side effect and redraw and explaining how `useMemo` and `useCallback` actually need to be used [0] and made me think of Stephen King's Langoliers.

It occurred to me that "React is the new IBM" [1] It has become so dominant in the market that no one can get away from it. But that also means that it can no longer innovate. Andrew Clark's twitter post *acknowledging* that signals and fine-grained reactivity would be better for performance but that the React team doesn't care pushed me over the edge of frustration.

I think that React finds itself not too far off from where IBM was at the micro-computing revolution. IBM had become too beholden to its market and too arrogant in their own success to see their own downfall.

The traffic and feedback on the second article is an indication that there are a lot of folks out there who are really, really dissatisfied with the state of React.

[0] https://chrlschn.medium.com/8eb7bb72c87

[1] https://chrlschn.medium.com/react-is-the-new-ibm-6af2f4b04e5...

React definitely continues to innovate.

Functional components and hooks were a huge innovation to class components and significantly improved the ergonomics of the library. That was only a few years ago.

The team is actively working on RSC (react server components) which will have a similarly large impact on react's capabilities.

Frameworks like remix and next will be able to leverage and build on this to create even better systems for building apps.

The whole signals blow up event is weird to me. Seems to be a loud and extremely small minority making a fuss around it.

IMO React continues to dominate over others (Vue, Svelte, Angular, Solid etc) because its just better - it embraces JS (no v-for, ng-for, non JS language) and strictly sticks to the idea that the view is a function of state.

All blow up events come from a loud and extremely small minority. But whether they are making noise or signal, does not depend on number of people!

React continues to dominate others because it meets baseline criteria for a js framework. And has corporate backing while Vue doesn't. Angular 1 was also popular because it was average js framework with google's backing before angular 2.

Implying that React remains popular for purely it's technical merit is utter nonsense. Because if react was really technically better, then no one would have migrated to Vue, solid and svelte or angular for that matter

> All blow up events come from a loud and extremely small minority. But whether they are making noise or signal, does not depend on number of people!

Fair, this instance is 100% noise imo.

We're engineers - we should be able to judge when something is silly.

> React continues to dominate others because it has corporate backing while Vue doesn't. And angular was popular for the same reason before angular 2.

I have never heard anyone in the last few years say react is better because it's backed by FB. I pick it because it embraces JS (unlike Svelte), doesn't reinvent the wheel (ng-for, v-for), and has a track record of maintaining backwards compatibility (unlike Angular re Angular vs Angular 2, hey its google what else should you expect). Class components continue to work 100%. Angular is backed by google - a much bigger company than FB and its nowhere close to as successful.

> Implying that React remains popular for purely it's technical merit is pure nonsense. Because if react was really technically better, then no one would have migrates to Vue, solid and svelte or angular for that matter

Some companies like to experiment, or have very unique challenges for which they find other tools better. I avoid Angular and Svelte - both have made such odd decisions. Some people do just prefer one tool over another! There will never be any set of capable tools where 100% of people select the same one. That's the variation of life.

Per the article's comment on forms and react and the messiness that ensues, well we're engineers. We can't expect a single library to solve every problem. We should be responsible for avoiding bad patterns like throwing from state into react state. It's 100% not necessary and should be kept separate.

You picked it because others before you had already decided and that was based off of the facebook name and backing. No one expected facebook to take such a pr hit over the last few years but ignoring why it become market leader misses the angular breakage event where everyone flocked from Google's framework to facebook's framework.

The reasons for not using other frameworks seems copycat without logic. For example vue uses v-for I don't want to have to learn a handful of obvious tags like v-if or v-else but then choosing react which has adopted jsx something that requires converting standard html and learning more to get you to the same place.

FB's reputation has no bearing on my choosing react vs svelte vs x or y or z.

I continue to pick React for projects because it's better than the alternatives - not because others before me have picked it and I'm just copycatting.

I can understand why some dislike JSX. I happen to think it's a great abstraction that elegantly combines the declarative nature of HTML and the power of JS.

It's always worth noting JSX can and is used in libraries beyond React (hello Vue!) which further demonstrates its composable nature and flexibility.

"Doesn't reinvent the wheel" they literally created a whole new language called JSX, I have 13 years writing JS and I dislike React and JSX is one of the reasons. As far I can tell reason it's picked a lot of times now it's market share, people see that is more popular than the competition so they try to learn it, creating a feedback loop that just makes it more popular.
JSX has been around for 7 or so years... that's a good amount of time. Over half of your 13 years :)

Do you avoid JSX when using Vue or other libraries that support JSX? Are you invoking the library function directly - React.createElement or vue's equivalent instead?

Yes I do, the only language I use for my personal projects is Typescript; I think JSX, .vue, .svelte they are all a mistake, JS is more than enough if you really need to use it to compose html.

    div('#wrapper',
        div('.container',
            span('.big', `It's not that hard`),
            button('.red', {route: home}, 'Home!')
        )
    )
You should give Clojurescript a serious look. You can use that approach, but the resulting code is... well, readable.
There is nothing readable about JSX, "<" will always mean minus-than and ">" will always be greater-than.
I actually like JSX a lot, but I'm baffled when people act like the very thin DSL used by svelte is any more unapproachable than JSX, or like JSX is somehow more javascript when it's a mish-mash of extended HTML (don't forget to use key as needed, and className), React components, and JS (expressions only, not statements... and weird-looking ones at that)
> don't forget to use key as needed, and className

Those are part of React, not JSX itself. Compare Vue's use of JSX, for example, which just uses `class` and `for` instead of `className` and `htmlFor`.

React just went for JS naming of the attributes instead of html naming of the attributes. Reasonable, if annoying, choice.
I recoil from svelte and such because when I see someone trying to invent an ad hoc language inside html attributes I get flashbacks to "transcluding" "directives" of Angular 2.
JSX is a simple transformation of nested JavaScript functions, but the custom DSLs used by other frameworks is string templating, which is kind of an inversion of how JSX works. JSX also has extremely good support in just about every editor and it supports TypeScript, which is not true of every DSL.
JSX isn't a new language, it's syntactic sugar for React.createElement() or whatever other pragma you prefer (like the Preact or Vue equivalents).
Call it what you want, still is the worst kind of syntatic sugar, the one that forces me to use a transpiler but its full of footguns, like being unable to use "class" for the "class" attribute and I have to use className instead, or the one that has no syntax sugar for conditionals so instead you write horrible stuff like {isValid && isApproved && foobar && <div>...}
If you're going to call something a footgun, make sure it's an actual footgun and not simply using a different naming convention than the one you want. You want the HTML name while React uses the Javascript name.

https://developer.mozilla.org/en-US/docs/Web/API/Element/cla...

https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelEl...

It is a foogun because is only for a few specificic attributes (class) that it uses this specific convention, for other attributes it uses the normal HTML attributes, for example in JavaScript to add aria labels you do stuff like "ariaLabel" when using react you have to write "aria-label" instead.
If you look at library popularity more broadly, you’ll find over longer periods of time only those people enjoy working with actually continue to grow regardless of previous momentum. People really do move on if it doesn’t work well enough for them.

Take React form libraries for example [1], redux-form used to be the most popular by far, was followed up by react-final-form from the same authors so people naturally flocked to that. But that is now clearly seeing a decline as react-hook-form, a library that started from zero, is a lot more pleasant to use.

[1] https://npmtrends.com/final-form-vs-formik-vs-react-final-fo... (set to 5 years)

AngularJS and Angular (what you referred to as Angular 1 and 2) are completely different frameworks. It’s a branding issue, not a technical one. Angular, from version 2 to 15 in the past 8 years, has been completely backwards compatible, and even stayed on the same paradigms. Angular code from 8 years ago looks almost the same as modern code. Which is much more stable than react’s codebase.
>It’s a branding issue, not a technical one.

I mean, for a single version bump (Google called it Angular 2.0) to render not only the code not migrate-able, but the entire paradigms on which the framework was based on is basically unheard of in an enterprise-targeting framework.

That’s an egg-on-face technical fail.

AngularJS and Angular are really the same product. Angular 1 turned into Angular 2 turned into Angular 15. That’s far from different frameworks, even if in between versions you’re essentially learning a new framework.
Vue is more akin to the old way of doing things with static templates (Jinja, Mustache, Erb, PHP), just with a dynamic twist.

React is not perfect, it's bloated, but the reason it took off is that it brought something new to the table as a general and programmatic way to construct UIs. Being a child of Facebook helped it achieve dominance but considering that before React we had angular (shudder) and jquery, React's success was well earned.

React will be replaced when something actually better comes along. The current contenders seem to want to return us to the technology of the past, it didn't work then and it doesn't work now.

Everyone is going back to "past technologies" like SSR, being old tech does not mean obsolete, send html directly to the browser in most cases is better than render them in the client, I think the better approach in theory is the island architecture that I saw on Fresh/deno and Qwik, both feels more like how we used to work in the past, minimal JS send to the client and more HTML send from the server.
SSR never faded and has always been an important requirement. Especially if you wrote SEO sensitive SPA's. We are not going back to SSR but are able to combine both SSR and SPA's more easily, as is indeed the case with dynamic islands and for instance React Server Components.
Not sure if you've worked with Vue 3's "composition API", but it is very different from Vue 2's "options API".

The composition API is bliss.

What's more important with Vue and fine-grained reactivity is that it is very forgiving of mistakes and poor practices that in React would cause much more significant side effects and performance issues.

Vue in general has been a godsend to me at least. When I was in college, we used AngularJS for web development courses at the time. My first job had me working with Qt and Tkinter. When I finally had the chance to do web development again, my team chose Vue and it was so easy to pick up from my AngularJS background.

My current team is using Vue 3 with the Composition API and it is way more forgiving with mistakes than the Options API. I've helped transition 3 developers so far to Vue 3 and they all love what Vue has to offer when compared to React.

Functional components were introduced in 2015. It’s a little worrying if that’s your first example of how React definitely continues to innovate.
React isn’t moving fast. React server components were announced two years ago and are still not available.

That said, as a low-level library it should not move fast; it should make sound design decisions while maintaining compatibility. It’s completely open to frameworks with more opinions and friendlier DX to be built on top of it.

>Functional components and hooks were a huge innovation to class components and significantly improved the ergonomics of the library.

I see this said a lot with particular regard to hooks, and to this day I just can't buy in.

For whatever problems class components have, they enforce a general layout of the component in a way that hooks don't. Reading some codebases that are all in on hooks feels like the wild west and is frankly nightmare-ish to untangle.

> (Vue, Svelte, Angular, Solid etc)

> it embraces JS (no v-for, ng-for, non JS language) and strictly sticks to the idea that the view is a function of state.

So does Solid No?

It's more like React is the MFC to HTML5's Win32. A not very good API with a near monopoly that people spend lots of time wallpapering over with ever more elaborate frameworks that end up being used only for distribution reasons.
It’s a pretty great API, I’d say! The alternatives also have their own warts.
That's a novel take. What justifies Win32's claim to greatness in your eyes? Do you mean by the standard of the time, or even today?
Admittedly I haven't worked on a large multi team react project before but I thought the whole point was that Facebook found React scaled well with teams (vs the state of the art at the time)

Not only can you componentise your UI code, but you can componentise your UI system meaning teams can develop independently of each other...

That's not what I see and hear though. People complain often about how complex things become with React and simple things take a long time to set up or develop, compared to rendering a simple template on the server side.

Usually people are not FB and people often do not have the same kind of strict development rules or enforced discipline, nor are they as many people as FB. Maybe the FB tool is not right for them.

Where React usually gets complicated is when non-trivial state gets involved.

Once you have state that needs to span your application and prop-drilling becomes too much of a drag, the misalignment between React's "pretend we're going to redraw everything" and "I'm only changing this one field in my state" causes most of the issues with React.

Calling React the next IBM is giving React way more credit than it's worth. Sure, basic knowledge of React will land you a frontend dev job pretty much anywhere in the world. However most of that work will be maintenance. If anything React is the new PHP.
Bad analogy. PHP will remain relevant long after React is dead and just a bad memory of the past.
Are you saying that React is bad because a Junior Developer cannot bother to think about caching or at least open introductory materials before using a framework? If that's the kind of problems you deal with, that makes React one of the greatest framework ever.
The purpose of a good framework is to make developers productive, regardless of their level of expertise.

A junior dev isn't going to be build as fast or as clean as a more experienced dev, but a good framework promotes speed and provides guardrails to prevent mistakes.

To that end my experience with React -- same as the author's -- is that React does not have this characteristic and provides many ways to shoot yourself in the foot.

A side issue, but... can anyone tell me why people say "the orange site" instead of just saying Hacker News, as if it is a bad word or a secret?
They're just showing off their cleverness.

It's not even orange for me. I changed the "topcolor" in my profile settings to d0c8b5 - a darker shade of the body background color. Now the only orange thing is the Y logo. Much easier on my eyes this way.

It’s been irking me as well, so I looked up “the orange site” in HN search and apparently it’s a euphemism some people who dislike HN use on Twitter.

I’d love to know who started using it first, though.

I've been working on a React side project for a few months now and looking at my company's apps plus posts like this I think people just miss the point. Stuff like this:

>Things get more complicated when you start using React Context and start signalling updates in a parent component. The render cascades. Maybe one component fetches some data, some component remounts, and you run your state update again, delayed by a few seconds.

This is just doing it wrong. State should change in response to user inputs. Ultimately, React is f(newState) => UI. If that function isn't pure you're gonna have a bad time. It's hard to blame anyone though. The docs suck and most of the tutorials you find get it wrong one way or another.

That said, there's kind of a reason why functional programming isn't more popular. It can be hard to grok and there can be a significant performance overhead. There's also a reason why this sort of implicit programming isn't as popular as imperative style. It's hard to predict what the implicit behavior is and footguns abound.

The example you highlighted as "doing it wrong" is pretty typical for an autosuggest component: Input updates trigger some request, which propagates to some list somewhere else in the dom. As it's loading, a spinner is shown, but when results are retrieved, they're updated again. Throw in apollo to the mix or some other request library, and context is used.
Think you're gonna have a bad time. Should be something like:

function handleChange(e){

  getAutoSuggestions()

  setLoadingState(true)
}

^ Side effects happen in response to user input

function getAutoSuggestionsCallback(resp){

  setSuggestions(resp)

  setLoadingState(false)
}

^ No side effects

> Ultimately, React is f(newState) => UI. If that function isn't pure you're gonna have a bad time.

React is not that at all. Unless your UI is very simple, React is not f(newState) => UI. React isn't functional. More on that here: https://mckoder.medium.com/why-react-is-not-functional-b1ed1...

You are both right. React components should render based on state that is managed by React, such that the rendered output changes only if the state changes.

The complicated bit is the handling of events and changing the state. Hence why you get Redux for state but there is no “Redux for views”

React very heavily pushes "component lifecycle" events, since it was class based up until now with hooks. That is, changing the state in the view function itself.

It's not wrong, it gives you one kind of separation of concerns: components. But "the view is a function of state" is completely misleading IMO.

setState is a convoluted way of passing the newState to components.

useEffect is a side effect and if you use it you're gonna have a bad time.

> useEffect is a side effect and if you use it you're gonna have a bad time.

Right.. but then you can't really use React for building serious UI.

From what I've seen that's like saying you need to use salt to be a good cook while pouring a bucketful on a salad. Perhaps it's technically true but from what I've seen you can build pretty complex UI without useEffect if you follow the rules.
You have to use it, obviously, but it should be used for side effects primarily. A good indicator is if all the values in your dependency array are react props/state, you're doing it wrong.
You can build serious UI’s without useEffect.

But it’s a powerful escape hatch like rust’s `unsafe` block. Rust can do amazing things to ensure safety of your program, but there’s still times where a human can do it better.

By signposting that, keeping it to limited blocks, and wrapping it up in a safe function you get the capability to do hard things, while exposing a safer API.

useEffect is similar, it lets you write the imperative synchronisation logic. For example if you need to interact with a DOM element that only has an imperative API, someone needs to do the work somewhere to wrap it in a declarative one. You can do that in a component with a useEffect hook, and then expose a declarative API.

It's still using the useEffect hook, but just wrapped in a useFetch or something. So technically you're not building a UI without useEffect, just hiding it, no?
How far down the rabbit hole do we need to go?

Because at some point your function call is manipulating registers on the CPU. If we go even further, the CPU needs to load its next instructions and then the data required.

Point being, we abstract and encapsulate complexity and provide a simpler API around it. It’s the only feasible way to manage the inherent complexity.

React builds up a virtual description of UI. react-dom and react native take that description and synchronise it to the UI layer.

If you need to do something extra, that they don’t handle like managing a map widget (ie mapbox) in React that only has an imperative API, it sure would be nice to do that yourself.

You can build a UI without useEffect. You can hide messy implementation details inside a well tested component, and contain where useEffect is being used.

And, you can understand how useEffect works so that you can use it without it having a negative effect on you.

It's just that "You can build a UI without useEffect."

and

"You can ... contain where useEffect is being used."

are not the same statement. Maybe I'm being pedantic, but when I read "build without X", I think there is some method that can be used to avoid X, not that I can hide away X.

They’re not the same statement. Both are correct. But as always, the nuance is critical.

All declarative code eventually runs something imperative.

And anything non-theoretical is going to have side effects somewhere.

Painting to a screen is a side effect.

Reading a file is a side effect.

Software gets messy when it intersects reality.

But, we can do quite a lot by staying in a theoretical realm. You can build a whole UI in the theoretical realm, where no side effects exist.

When you actually need to run it though, you drop out the the theoretical and into reality. Now there’s side effect’s everywhere.

So you contain them. Encapsulate those side effects into composable blocks. Test them extensively. Offload that work to someone who’s just focussed on managing them.

Updating the DOM is a side effect. Making a network request is a side effect.

Contain them, test them, and then you can stop thinking about them.

If someone else has done all the work to contain side effects, you can build a UI without them.

If you need to fetch a piece of data when the component loads, how do you do it without useEffect?
You don't do that.

Why would fetching data depend on whatever is being rendered?

You know what data you need or not need before rendering anything, or you will be in a world of pain.

I am not sure I am following. Say your homepage has a link to a page that shows the top scorers in a league. Where/when does the fetching of the top scorers happen ?
Sure:

- Click the link to show top scorers

- Initiate fetching the data

- (The view may change to indicate you're loading the top scorers, if you want, that's a different matter).

- Receive the data, the view changes to display the data

This is opposed to:

- Click the link to show top scorers

- View changes to show top scorers component. A component loads, or mounts, or inits, or does something which triggers a data fetch

- Receive the data, the view changes to display the data

Your app "knows" you need the data when the user clicks the link, no need to involve the view components into this.

This gives you the ability of adding a lot of complexity to how you fetch the data that is best handled outside a UI component (like caching, reusing it in other components, error handling, retrying, throtling, whatever), while saving you from a whole class of problems where a misunderstood component lifecycle has consequences for your data. Frameworks like React or Angular are going to try to help you by caching outputs, reusing components, dropping updates for the same frame, prerendering, preloading or anything really. If you fetch data when a component does any of that, suddenly you have to care about it and fully understand it. The abstraction leaked. If you treat the component as close to a pure function as you can, things become much simpler.

This applies to relatively big, relatively complicated apps, controlled by a single entity, where it pays off to prioritize simplicity.

Okay, I get the idea. How are you solving these issues:

- how is the data fetch completion signalled to the component?

- how is the data piped into the component?

Would be happy to be pointed to some example code if you have.

> - how is the data fetch completion signalled to the component? > - how is the data piped into the component?

Both have the same answer. When you fetch the data you put it in the state, and then you render your components based only on that state.

If we're talking React the state makes it into the component through the props (pure UI component) or, if using Redux or similar, some kind of hook that triggers a rerender when the store changes (useSelector? My React-Redux is a bit rusty).

The point is not to worry anymore about change detection and rendering, because the framework takes care of it by being either fast enough that it can run on every change, or smart enough that it can tell when it's not necessary to re-render (caching, change detection).

Of course, this setup with redux etc makes a lot of sense for bigger apps with lots of state coming from different sources. I don't have any specific example I can point to, but any redux implementation examples could help. I use NgRx with Angular, and the docs are OK at explaining the flow of data.

Thanks, this was useful.
The linked article doesn’t convince me, instead it shows a misunderstanding of react and hooks.

> But then they added hooks and useState and useEffect and so on, which made the functions impure. The problem with hooks is that they “hook into” React state and lifecycle features, which means it is modifying global state.

React components don’t update the dom every time they run, they update the fiber tree / virtual DOM.

Only in the commit phase is the DOM updated and side-effects are run.

My rough understanding is that:

Hooks, excepting useEffect, all run in the render phase.

UseState hooks store data in the component in the fiber tree, and capture a sequential list of updates when you call setState.

Algebraic effects can seem a bit odd at first, but it’s really like a generalised try/catch. Instead of storing state in the function itself, you reach out up the stack to the component and store it there. And every hook you call from your hook stores it there too.

It’s why call order is important, because it’s how they know which is which.

You don’t modify any global state though.

The actual component function needs to be able to be called multiple times in the render phase (which just updates the vdom), and must have the same output each time, if the inputs/props are the same.

Every now and then, the tender phase can be interrupted to run the commit phase, which synchronously brakes a snapshot of the vdom and applies all the needed updates to the outside world.

Perhaps it’s better to think of as

render: f(props) -> descriptionOfUI commit: apply(descriptionOfUI)

I would absolutely say components and hooks are functional, with algebraic effects. And that the resulting data struct from those components, is what’s used to produce side effects.

Even useEffect, is a description of a side effect to run, it doesn’t run in your hook, it runs on commit with all the other side effects.

There’s a ton of optimisations under the hood but that’s roughly my understanding of how it works.

> ...and capture a sequential list of updates when you call setState.

In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value.

> ...you reach out up the stack to the component and store it there.

FP functions are not allowed to do that. In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should not do anything beyond return a value.

> It’s why call order is important, because it’s how they know which is which

In FP, functions can be called in any order (unless one function needs the return value of another), and the final result is not affected by the order.

> You don’t modify any global state though.

If you have state it is not FP, whether it is global or not.

> In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value.

Oh, yes, they are allowed to do that. You capture the effects into a list, and return the tuple of list and return value. If you feel like it, you wrap that into a monad to pretend you are only "returning" a single thing.

> In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should not do anything beyond return a value.

You mean explicit parameters (props) and implicit parameters (context), right? I thing you forgot the latter. Implicit parameters have existed for quite a bit, for example in the reader monad.

> In FP, functions can be called in any order (unless one function needs the return value of another), and the final result is not affected by the order.

Yup, except if you write a bunch of functions and store them in a list with the intention of applying the result of the first entry of the list against the first entry of the list. Now, if you construct the list of functions as effects (by hiding them behind a monad) you find out that you need to call the effects in the same order as to construct the list of effects in the same order. This doesn't contradict FP, it contradicts your mental model of how React is supposed to work.

> If you have state it is not FP, whether it is global or not.

The state resides in the runtime executor, exactly like Haskell's IO monad. Again, this contradicts your mental model, not React or FP.

I think you may be missing the forest for the trees. The point of FP is that you can glance at a function and say 'this is obviously correct' without having to work out the state and context of every call.
But you can do that with algebraic effects. That’s kind of the point.

You keep the clarity of declaring what you want to happen, and abstract the how to the effect handler.

None of that is true in React hooks. The negative sentiment towards hooks that you see here is because it is weird and complicated. Want to see how much simpler code can get when you code without React or any such fat frameworks?

Take a look: https://github.com/wisercoder/eureka/tree/master/webapp/Clie...

You just need to know JavaScript, HTML and CSS, not much else. The code is simple, and yet maintainable. No need for hooks, useEffect, useState, useMemo and all that crap.

How can you ever be sure that your state is valid when you’re putting it on the DOM? Worse yet, only parts of the state is stored there.

I can’t really call this code simple since it had to resort to timing hacks to get its functionality in order. A random 250ms delay and bam, bugs you cannot reliably reproduce

Can you clarify what you mean here? What state is in DOM? Do you mean the state inherent in input elements? What timing hacks are you talking about?
The first file I looked into was the combo box. This is what I consider to be a timing hack:

    private onDropDownMouseOver(ev: MouseEvent): void {
        if ((new Date()).getTime() < this.whenScrolled + 250) {
            // We automatically get a hover event when we scroll, ignore it in order to keep our current highlight.
            return;
        }
        const element = ev.target as HTMLElement;
        if (element.classList.contains('combo-dropdown-item')) {
            addClassExclusively(element, 'combo-highlighted');
        }
    }
Some event stores the time it has been fired, and this method checks that it has not been long since the firing. With react, which item has the highlight would have to explicitly be in the state and completely remove the need to do this optimization.

And this is an example of what I consider state being stored in the DOM:

    private isDropDownVisible() {
        return isVisible(this.dropDown);
    }
The view has logic that depends on whether the dropdown is visible, which is checked by dropdown.style.display !== none. Now any element in your page has the power to modify this component’s logic by modifying the DOM
The timing hack is a workaround for a browser bug. The exact same hack would be required in React as well. What is this browser bug I speak of? Browsers send a spurious "hover" event when you stop scrolling, so that the item under mouse can be highlighted. This can cause problems in some cases.

> Now any element in your page has the power to modify this component’s logic by modifying the DOM

If some part of your application intentionally does something wrong, it can break your application whether it is React or some other tech. In this particular example, if you prefer, you can have a member variable to keep track of whether the dropdown is visible or not. Still no need for React.

As you can see, none of the complexity of React is necessary. No need for hooks, useEffect, useState, useMemo and all that crap.

Would it, though? Keyboard event sets highlighted item key/id; scroll event pops up, sets the highlighted item again, then react does not do an additional render because the state has not changed since the keyboard event.

The code does not have any complexities of hooks (which are just a javascript approximation of do notation, I don’t believe it is that complex), but what it does have is the requirement to write down all of your mutations correctly, where every “down” is an exact opposite of the “up” and does not leave any artifacts—with no way of formally checking. At least for myself, I think that level of discipline is unreasonably high so I tend to prefer stricter typed functional solutions where the view is composed purely from the state

I'm not sure what timing hacks you're referring to - using setTimeout() with 0 delay? I think that's being done to defer execution of heavier functions and let other timeouts be handled first. Seems more like an optimisation rather than a hack to achieve basic functionality.
https://github.com/wisercoder/eureka/blob/master/webapp/Clie...

I love how you do React. I mean, what's more react-y than blanking the page then appending HTML? I'm gonna call that Rejqueryact, because it's jQuery inside React.

I'm not seeing React being used, though, just TSX/JSX? All the view and state updating is being done manually, but it looks fairly well-organised. There are small optimisations like debouncing onInput with a timeout (avoiding rapid re-rendering/reacting to every character typed): https://github.com/wisercoder/eureka/blob/master/webapp/Clie...

Is this really much more complicated to implement than the equivalent implementation in React? (It's probably a bit more responsive, at least.)

I think they’re referring to how Reacts mental model is to wipe the page and rerender. The earliest versions basically did that, and then they started diffing and applying the diff.
They're referring to a specific bit of code in that Eureka repo that sets innerHtml = "" and then does .appendChild(). They just apparently didn't notice that the code doesn't use React at all (and is meant to demonstrate the use of vanilla modern JS without React).
Yep that’s what I was alluding to as well. I’m pretty sure they noticed it wasn’t using react.

The comment was a reference to the fact that if you don’t use a framework, you’ll end up a building one anyway.

We’re coming at this from different mental models.

The code you linked is what React helped me get away from. There’s multiple files in different folders for one screen. It’s hard to see how it composes, which is a useful boundary as it lets me know in the scope of that part of the UI.

UI is _hard_. There’s complexity that needs to go somewhere, and I’m one of those who prefer to push as much if it that isn’t business logic into a framework.

This becomes exponentially more important for every engineer you add. Go success is along these lines, with typically only one way to do things it’s much easier to share code.

From the code you linked, I could find my way around, but piecing it all together took a lot more work than any of the frameworks.

You mention only needing to know JS, HTML and CSS. But you missed that you still need to know how all that code is put together, what calls what. How it updates. React needs this too, the only difference with it being a framework is that knowledge transfers to a different project.

And to be clear, I’m not saying you need to use react or a framework—going your own way is often how amazing new things are found.

What I am saying is your attitude isn’t helping you here. React is still arguably the most used framework[0]. There’s a reason so many of us like using it and it’s what you described as “other crap”.

Frameworks help with collaboration, in the same way programming languages do. To do anything interesting with a general purpose language, you’re either going to use a framework, create a new one with good documentation and build a community of engineers around it, or build a halfbaked one that few people understand.

I’m open to other ways of doing things. It’s a good way to grow. I learnt SwiftUI a little while ago, and while I don’t use it regularly it improved my understanding of UI building. I learnt imperative UI API ages ago, and know for sure I want to avoid/contain that into a more manageable declarative approach.

[0] https://trends.builtwith.com/javascript/javascript-library/t...

It is idiomatic JavaScript. If you learned Java at the university you'll immediately be comfortable with the code. Now consider React with hooks. It is neither OOP nor functional and it looks alien to anyone who knows idiomatic Java or JavaScript. Would you recommend a youngster learning programming to learn React? I wouldn't, because it is so frankenstein. This article makes that point better than I can: https://medium.com/codex/can-we-all-just-admit-react-hooks-w...
JavaScript brings together so many paradigms, I can see strong cases for multiple different expressions of the language.

We didn’t have classes until ES6. And they’re not real classes, they still use prototypical inheritance under the hood.

If you want truly idiomatic JS, you shouldn’t be using classes. You should only be writing functions, and build your class-like objects with prototypes.

On a practical level, I absolutely recommend new engineers learn React. The job market is enormous, it’s a skill the market still rewards well.

And it’s a very productive framework. It rewards you for learning it, with better collaboration and velocity.

I would say the same for the other major view frameworks too, but React still has the biggest job market.

Until ES5, the industry thought JS was a Frankensteinesque monster.

Until maybe 5-7 years ago, anything that wasn’t OOP was considered a bit weird.

Calling any of these languages weird, is like policing English speech. We borrow so much from other languages that’s words have multiple meanings. Pronunciation follows contradictory rules, and regional dialects can be hilariously incompatible.

There’s a few languages closer to French, which has a strict control on what the French language is. For example, Go. There’s really only one paradigm them, only one way to do things.

Like it or not, pushing the boundaries of language design and framework design is how we improve as an industry.

You can’t not like a new thing because it’s weird at face value. You risk missing the forrest for some moss on a tree, and being left behind.

And sorry, that’s the same article this comment thread spawned from. I didn’t find it convincing at all, it’s let down by a lack of understanding in a few key areas.

No. The point of FP is "minimize state and effects so that the code is easier to understand", not "write it in FP style so that by magic is correct".

For exactly the same reason OO is "put the code that manages the state near to the state and split it in manageable parts" and not "dog inherits from animal therefore the code is correct".

Leave the faith at the church and approach code with science.

No matter how sophisticated the language we use to describe it: it’s still a bunch of side effects and state.

If you’re fetching some data in a useEffect you might not get a result that day.

If you’re updating something with setState, you are still managing state. UseState is a reference to a mutable object now.

You’re simply not getting the same answer every time your now impure function is called.

In order to do understand what’s happening you need to recreate the whole state. Which is exactly the same reason state management is hard as in OO or procedural.

You might have a mental model that explains why it is still FP, but for all practical purposes of that paradigm it isn’t.

Wow, I've never seen a reply that so thoroughly fails to address any of the points it's trying to reply to.

When you reply to "in FP, functions cannot do that (change state anywhere)", you say "you are allowed to do that: capture the effects into a list, return the tuple of list and return value" without realizing you're saying exactly the same thing?! The distinction between "return value" and "return value plus some other thing" does not exist. What matters is that the function's only observable modification is in what it returns, be it one value of many. This is basic FP.

You return a tuple, which first element is the value the function would return (I/E "return jsx stuff") and the second value is a list of operations (effects) you intend to perform I/E "I intend to change this variable to value X", "I intend to run this external function when these values change".

The function's only observable behavior is that it returns a tuple with JSX and some effect descriptors.

No, this is not basic FP. This is somewhat advanced FP.

I find it's best (if side effects and state mutation make you nervous) to think of hooks as essentially part of the function signature of a react component, both on the parameter side, as well as on the return side. They are not written as such, because of syntactic limitations of JavaScript, but essentially a react component that starts off like this:

   function MyComponent({}) {
      const [count, setCount] = useState(0);
      const [active, setActive] = useState(true);
      useEffect(() => if (active) setTimeout(1000, () => setCount(count+1)), [count, active]);
      ...
can kind of be thought of as if it accepts an extra hidden set of parameters, kind of like this:

   function MyComponent({}, hook1 : useState, hook2 : useState, hook3 : useEffect) {
      const [count, setCount, hook1Result] = hook1(0);
      const [active, setActive, hook2Result] = hook2(true);
      const hook3Result = hook3(() => if (active) setTimeout(1000, () => setCount(count+1)), [count, active]);
      ...
      return [<div></div>, [hook1Result, hook2Result, hook3Result]];
   }
In this version, those hook functions are side-effect free, pure functions that our caller provides us with, closed over the previous stored state of our component in the tree; and when we return the results along with our rendered output, our caller has the new state of our component together with our desired DOM.

Instead of forcing us to write all that extra code, route those extra variables, and figure out the metadata mechanism whereby the caller of the render method figures out what hook functions to supply, the rules of hooks let you use JavaScript's imperative, procedural syntax to call hooks which are implemented using ugly side-effecting impure techniques, but in a way that pulls off something semantically identical to this pure functional flow.

It's a pretty neat trick, honestly.

Don't call this functional programming. If you call setCount() then this is not functional because your function is doing something besides returning a value. In fact, it is setting state, which is against FP principles.
Okay. But is it against FP principles to write software that runs in web browsers then?

Because web browsers exist, and they work in a nonfunctional way.

So to interact with one we need to do a little bit of imperative code.

And then react lets us figure out what to do when the web browser responds to that imperative code by letting us run a largely functional program.

Which is pretty neat considering we’re doing so in JavaScript.

The thing that we’re after here is not a badge that we can slap on our code saying ‘certified 100% functional’. We are trying to write code using patterns that help us reason about and structure what we want the computer to do, avoid bugs, and ship software.

If react managed to squeeze a surprisingly functional pattern into a JavaScript library to that end, can’t we just applaud the audacity and enjoy using it, without nitpicking that they didn’t actually reimplement the lambda calculus?

Why is it necessary to use FP to write software that runs in web browsers? To be sure, FP has benefits (such as, it is much more straightforward to reason about FP code), but those benefits are not applicable in React. So why pretend it is FP?

React is neither FP nor OOP. More on that here: https://medium.com/codex/can-we-all-just-admit-react-hooks-w...

Web browsers are agnostic to the programming paradigms employed to code websites in. We might need to bend JS a lot to get FP though. JS has some quite procedural roots/basics. For example the timer API (setTimeout and so on).
Most of the ideas at play here come from the functional programming world, which is why it’s often viewed from that lense.

React builds on functional reactive programming, something the FP world is known for[0]. I’m not saying it’s pure FP in the dogmatic sense, I just wanted to point out it’s closer to FP than the other paradigms.

Without the ability to interact with the outside world (side-effects), FP is not of much practical use. Not to say it’s bad or shouldn’t exist, just we need to add to it a bit to make it useful.

Why would we do that? Because the underlying ideas and principles provide a great foundation. Building on that to get FRP and algebraic effects, monads and so on, is very different to starting from OOP and brining FP ideas over.

React hooks are an interesting and tricky thing to put in a box, because they’re almost monads, almost thunks, almost algebraic effects. The interplay with fibers and components makes them hard to pin down, but they are much closer to functional than any other paradigm.

[0] https://wiki.haskell.org/Functional_Reactive_Programming

The web is (was) a pretty good example of something akin to FP: REST means all state is transferred with the response and then the whole thing is rendered in the browser. And then there is HTTP, so if you want a new page, you simple call another URL (like a function call). OK this is glossing over some parts like that cookies are also send, but they are additional optional arguments of that request (function call). That's what the mean (or meant, since the term is now muddied), when they say the connection is stateless.

What we have with badly written React apps now (90% approx.) is a UI, that is not at all behaving like a typical website and very far from being like FP. We often cannot simply go back with the back button and expect to see the same page rendered. I mean we can, but the websites will fart in our face, if we do. We do not get the ability to simple send a link to someone and have them see the exact same page. It is a huge departure from anything FP.

Furthermore from the dev perspective components feel more mainstream OOP than FP, since they store internal state and update it, which indirectly causes things I described above.

Not sure where people see the FP. Not sure they really have done any FP language before or tried in projects to strictly adhere to FP principles, because that looks a lot differently than React components and mixing state, layout and styling in JSX/TSX.

> React hooks are an interesting and tricky thing to put in a box, because they’re almost monads, almost thunks, almost algebraic effects. The interplay with fibers and components makes them hard to pin down, but they are much closer to functional than any other paradigm.

They're almost classes (/objects). The implementation is what it'd look like if you wanted to make a weird half-assed OO... thing. Property and method declarations, getting attached (ultimately) to an object. But it's FIFO access/calling, rather than using named properties and methods w/ a lookup step. And the declaration syntax is bizarre and hard to read. And they're slower than regular JS OO (because they add an extra layer of JS on top of it).

I don't know react details but set<X> are not effecting directly, it's just another iteration from prev -> next state (with the values given in set<X> hooks) which is functional.
I believe higher-order functions and callbacks are completely ok in FP, no?
The bit of react that is f(newState) => UI is the easy part.

The bit that is g(state, userInput) => newState is the hard part. In particular managing the scope of that newState.

Oh, and sometimes you need to handle h(state, asynchronousData) => newState too.

And then comes the fact that even though your f is _pure_, it also has to be _fast_, because it's going to run every time you get a newState.

In my experience redux-toolkit + redux-saga for async stuff usually work really well. In case of performance problems one can go with profiling + targeted optimisations (e.g. a separate store, some locally managed state).
Glad to hear RTK is working well for you! FWIW, we actually specifically recommend _against_ using sagas in almost all cases. Instead, we recommend using our RTK Query API for data fetching and caching, and the RTK "listener" middleware for reactive logic:

- https://redux.js.org/usage/side-effects-approaches#recommend...

Thanks, I wasn't aware RTK now has a saga-like "listener" feature - will look into it!

What I like about sagas are their simplicity & power (once one understands how generators & effects work), plus the eventChannel feature which lets one integrate with non-redux events. Good TypeScript support is a problem though, and I've had to resort to typed-redux-saga :/

Yeah, we specifically designed the listener middleware to do ~90% of what you could do in sagas, but with a smaller bundle size, simpler API, and better TS support:

- https://redux-toolkit.js.org/api/createListenerMiddleware

- https://blog.isquaredsoftware.com/2022/03/designing-rtk-list...

Event channels was something we intentionally _didn't_ try to replicate per se, and tbh I've never tried to use those myself. (But, I _suspect_ that you might be able to do something similar with listeners even though we don't have a specific replacement built into the listener middleware, and if you do I'd love to see an example in action!)

If you get a chance to try out listeners in your project, I'd definitely appreciate feedback on how well they work out for you - whether they solve your current saga use cases, what cases they _don't_ handle, anything we can do to improve the listener API, etc.

I had to rescue a redux-saga project that went badly off the rails. It was one of the most inscrutable and difficult to debug codebases I've ever had to work with. Forget completely about ever having a usable stack trace.
Yes, I guess you can abuse every technology. Sagas are always sideeffects and thus have to be used with restraint.

Sagas keep state (and you should keep most state in the redux store, anyway).

So, yes, you can go wrong, as with everything else. But it's better than using useEffect as an async framework.

Yes, absolutely. Don't use useEffect as an async framework, use thunks or sagas.

Remove most logic from the components into sagas,thunks and selectors.

That way your components will be smaller, more testable, easier to change, easier to reason about.

I get so lost in these conversations, because I've been the lead on a relatively complex React app for literally years now and none of any of this has mattered or come up in any way whatsoever. Our app is plenty fast/responsive, maintenance hasn't been perfect but it's been manageable, same with new features... The learning curve around context was a bit steep but we get it now and haven't had any issues since.

It's like you're speaking a different language to me, and I find that so weird considering we're using the exact same framework. How am I not having any of these issues?

I'm honestly at the point where I wonder if y'all are making things harder on yourself somehow, because I could see how getting obsessed with counting every single re-render and trying to overoptimize would result in the stuff you're saying while not actually impacting perf in a meaningful way.

I've been in the same boat with these discussions.

When I do encounter a component with countless re-renders as described, it is usually painfully obvious what causes them and easy enough to fix.

I think we're going too far if we're expecting React, or any framework, to be fool-proof to the point that we can just throw "whatever" we want at them and expect it to have peak performance.

Depends on what kind of so your building. For a while, a lot of the form libraries out there triggered huge numbers of rerenders and caused perf issues. That's still a problem, though some of it has gotten better uncontrolled components.

Timing-based UIs are (such as a sequence of triggered animations) can get really messy really fast. I've seen some really messy bugs in a app that had visuals and audio tied to different timers and user inputs in the app. We eventually moved all time-based animations to observables, which helped some

> a lot of the form libraries out there triggered huge numbers of rerenders and caused perf issues

Something I don’t quite get, doesn’t useRef just solve the re-render issue?

Sure, but then you're managing state and re-renders yourself. Kinda defeats the purpose of using the framework, right? The useRef() approach to fixing performance is the main reason why I think Signals are popping off. Users of frameworks like Vue and Svelte have felt this way for a long time.
I've worked on a form + animations based site ~2 years ago. Forms via higher-order functions, it was a full-stack NextJS thing. Without TS.

I had to eventually claw my eyes out and that solved part of my problems, at least I did not see the boilerplate and the ugliness.

Then soon after that we worked on a similar thing (form + draggable carousel with snap to grid animation) in Angular with Material.

And my conclusion is that whichever framework you pick, whatever libraries you end up using, you must have a strategy to allocate your time and maintenance budget, and many many many times the sane compromise is to write something in raw JS and encapsulate that in whatever the framework gives you, and move on. Don't try to solve it within the framework, because it's just not worth it.

Forms were annoying but `react-hook-forms` eliminated any random issues we had, and now forms are fine. Again, context saves the day here by letting me grab the form context within nested components to keep everything humming.

I don't know if we have any "timing" based components, though we manage global state using Apollo Client and again, haven't really had any issues with that.

This is why people use redux, keep state in a store and just do v=f(state).

Your app is the store, not the DOM.

It really makes things much simpler. The trick is to keep all the state in the store, including when things are loading, when some user interaction is happening but not yet complete, etc.

From your comment, it seems like there may be some problem if the user is interacting somehow, let's say in the middle of doing a drag and drop, and some data update comes in from a websocket, right? Well, if that's going to cause a problem for your render it's because apparently your data-updated function h needs to know if the user is doing a drag and drop. That should get put in the state when the user starts the interaction, and now h can know about it and react correctly.

Yes, it's more complicated than just have some component render based on the data you receive, but that's because it turned out that your app was more complex than you thought, it has more states you need to care about.

There's no magic wand, but this stuff works, just adds some boilerplate code but I don't mind.

> because it's going to run every time you get a newState.

Didn't have to in the past. Back with class-based components we had shouldComponentUpdate(), and lost that when components switched to pure functions.

> State should change in response to user inputs.

Absolutely not only to user inputs, but any kind of event: response, websockets, push notification, worker task finished... a million things beyond the basic "click".

> If that function isn't pure you're gonna have a bad time.

Hooks let you deal with "component lifecycles" which make that function not pure. Only the most basic toy react components are pure, everything is about side effects IN your views.

>> I've been working on a React side project for a few months now and looking at my company's apps plus posts like this I think people just miss the point.

The clue is in if everyone is missing the point but you, may be start with more introspection. :)

I will give an example of a side project I am working on. The homepage has two sub components, one when the user is logged in, one when the user is logged out.

Now, when the user logs in, the state of the homepage parent component needs to change, the state of the nav bar needs to change etc.

Your problem is in assuming newState is completely described locally which isn't always the case.

GP's post reads like a definitive example of Dunning Kruger. These are large-scope issues that the article highlights likely won't be apparent in smaller efforts that could be referred to as a "side project".
That's not what I said my entire exposure to React is.
I used Angular pretty heavily before switching to React.

At the end of the day, they approach the problem from two different directions, solve issues in two different ways, and end up with two different sets of challenges in terms of what's easy and what's hard in them.

I've definitely written React UIs that would be easier in Angular. But I've also crashed Angular performance through the floor trying to wire up a table display with Angular update hooks. Angular makes it easier to hide state-update dependencies in a way that causes really bad thrashing to reach steady state, which I've (anecdotally, generally) found harder to do in React because doing it in React involves writing a lot more code and a lot more cross-state dependencies.

I’ve happily used MobX for years. It comes with its own quirks but almost completely bypassed the awfully awkward state management that is React. Made my life 200% more enjoyable!
If you use Typescript, take a look at: https://mobx-keystone.js.org/

It's an additional layer on top of MobX that adds strong typing. I've been using it for an open source video annotation project and it's been amazing for keeping track of local state, cascading calculations of things.

Here's my "models" directory for it if you want a taste of how it works:

https://github.com/Rodeoclash/vodon-player/blob/main/player/...

Thank you! If only I had been a better programmer back then I'd probably have opted for a solution like this. Instead I had worked out through the year and made some highly custom system that resulted in very similar patterns. Too ingrained in my app now to consider new options but might be a good idea to build on top of those next time around!
Meh. The most important thing about React is you have to think like React wants you to. It's a very pattern-oriented type of development I haven't seen much of elsewhere.

Most of the footguns listed in this article are things you obviously shouldn't want to do because they're not React-y.

Some others would describe it as idiom-orientated.
Thanks! That's probably a better phrasing.
Forms are absolutely a problem, though. Forms not being "reacty" isn't going to get you out of needing them.
As react is only the core library and not a batteries-included framework, you will often find additional libraries that help with certain use-cases.

E.g. if you are dealing with forms a lot, I would strongly suggest using react-hook-form or formik.

If it's not batteries included if should not require people to add a huge amount of overhead to their projects to use it, stuff like JSX or create-react-app
> create-react-app

That's neither required, nor being recommended by the wider community anymore.

> JSX

JSX on the other hand I feel like is something that is essential to React (yes, I know that some people disagree), and one of the few things it should provide/require, as it forms a cornerstone of it's UX. Getting things set up to understand JSX/TSX has been smoothed out a lot now, and hasn't been an issue in any greenfield project I have set up in the last 2-3 years.

I do use react-hook-form! It helps a lot.
For reasons that I can't quite explain fully, I like angular much better. For me it's a shame that react won the battle and is used at every company now.
For me, Angular enforces a rigidity that seems oppressive at first, but once the codebase grows in size and complexity it all makes sense. In React I might find API calls nested in component effects, setting context that gets consumed or overriden god knows where down the tree; in Angular all of the API calls and state is isolated in high level services and it's very easy to follow the logic and track where those get injected and consumed. I also find it much easier to mock a service rather than mocking contexts for testing.
Angular seems like a step back to me. The MVC thing, while fine, introduces extra hiccups. Creating generic UI components is pretty tiring and using Angular material is pretty much your best option.

Upgrading to newer versions is a pain and also finding well supported third party libraries. React is much easier to work with since you don't always need to reinvent the wheel for time consuming things.

Hooks and simple state management with Jotai are also much nicer to work with than RxJs. RxJs requires a strange mental model and a lot of verbose code and functions.

Angular is kinda like Java, more code for less features. Great if you don't wanna think, meh if you want something exciting and new.

Not to start an unholy flame war, but if you were to start a new project and didn’t need to worry about the ecosystem or workforce, what framework would you choose? Vue? Svelte? Something else?
Honestly just use what you know. Unless your goal with the project is to learn new things or to have fun, than go with what is most interesting for you. Or if you are in a larger team, then talk to your teammates and try to get a consensus around what you are most comfortable with collectively.

I only advice against using a niche framework if you suspect the project is gonna be long-lived and managed by a medium to a large team, in that case pick the one of the big ones—React, Angular, Vue, or Svelte—which your teammates can agree with.

I'm interested in what's happening in the MPA space. The Page and View Transitions API that the chrome team is working on, partial update libraries like htmx and unpoly, etc. If payloads are tight and servers snappy, many of the concerns that led to complex SPA architectures in the first place have begun to wither away.
Hotwire and Stimulus are great. They’re widely used within the league of “sprinkles” libraries and it’s well maintained. You can use it with any backend framework. I use it with Laravel and it’s a pleasure to work with. But it’s not trendy or fashionable, so expect a lot of looking down at you for using it.
Svelte. If I really want JSX, then I would pick Solid.
Deno / Fresh.

I despise what NPM has become, and how complex / time consuming the build pipeline of front end apps is.

It’s still not a mature framework yet but hot damn does it excel at just getting out of my way and letting me ship stuff.

I don't know about Vue3 (I used in the past Vue2 only), but Svelte is similar to React, I'm migrating a small/medium project from React to Svelte and it feels too easy most of the time to port component by component, also to me, at least to this point, Svelte feels more performant and you have 100% control over the reactivity without too much `use{function}`.

I would recommend you to build a small project, maybe a Todo app in every framework you want to try, or maybe if you have a project, build a small part of it in each (I will pick the part that you think is the trickiest to build with React or the framework you are actually using).

Also I'll recommend to also check Qwik and Fresh(deno).

I just started one small project that is a single component that talks to our API and is rendered on an external website. I used lit-html for it. Very small, very fast library for this kind of thing. No build tool required. I choose my own (smaller, simpler, more straightforward) way of managing state.
I find Svelte phenomenal.

But I'm also interested in trying Solid.js and Vue, and for some types of projects I'd likely even go Astro+Svelte or Astro+React.

Hard to speak authoritatively on the matter though because over my career I've only done vanilla JS, jQuery, Backbone.js, React, and then Svelte, in that order, and each has felt like a leap forward in evolution

Standard ones I would like to try are Solid/Svelte/Vue

- Lit if I wanted to share components with other teams

- Marko if the site had lots of static content

- Qwik if speed was paramount

- Fresh too looks interesting

Stimulus and Hotwire (on top of Laravel or any other decent batteries included framework).

Not a single one of the many projects I’ve worked on in the last 10 years needed such a level of interactivity that it justified the trade offs of using react or any other frontend-heavy frameworks.

I’ve seen entire CRUD spas that would have been built in 20% the time if we didn’t have to build a graphql api, figure outs authentication and permissions, integrate that with a custom validation setup, integrate all of the above with the translations systems, coordinate deploys or do forward compatible migrations, etc, etc. so much energy (and money) wasted.

WC with LitElement (Shadow DOM disabled) for a SPA (if no SSR is needed).
Web Components, Service workers, Lit.dev, htmx, declarative shadow dom. These are the modern tools you need.
Solid JS It will have a very easy learning curve for React users too.
Be careful on spreading the statement "easy for React users", yes that's true for using JSX, but for React developers trying out SolidJS, make sure not to desctructure props, get rid of rerending function mental model, components only runs ONCE so reactivity works by tracking reactive elements(signals/stores) inside JSX or effects(createEffect, createMemo ect), that means no early returns. If a React developer (I've witnessed this with Twitch streamers), jumps into SolidJS blind without taking tutorial, they get lost into rerender mental model.
I'd still use React, purely to be able to use JSX without another templating language, and I think in its functional paradigm as well.
React hooks could have been very different with very minor touches. But at this point, a structure has emerged where you need to make extra efforts to work steadily. It wasn't like that at the core of React. Class components had their own problems. But you know how to solve them. I don't think this applies to react hooks.
The snark is strong with this one.

It's a pretty major rant, without putting forward an alternative.

The only viable alternative for me personally is VueJS and that's not my cup of tea either.

I like React. It makes sense mostly.

Is React perfect? No.

Do I like React's recent transition to focus server side? No.

But the problems it addresses are tough to solve.

Show me a better solution and convince me its tangibly better than React.

It's reasonable to highlight issues without presenting alternatives. If a valid alternative existed, people would have moved already and this type of post wouldn't exist.
> It is not obvious that your component re-renders on state updates.

I... isn't it? Isn't this like the first thing in the hooks introductory material? If you don't find this, yeah, hooks are gonna be a bad time.

I went and checked, and it is a bit buried at the bottom of the useState explanation when explaining what an example does:

> Line 9: When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.

https://reactjs.org/docs/hooks-state.html

I think they assume you'll figure out that it must do so to function at all.

This has been true even in the old class components. A component always updates when props update.
It's about state not props. But yes state is more or less implicit props.
I had a co-worker that assumed it worked template-style, where the value in the JSX would update and what's on the page would re-render, but the component function wouldn't be re-run.
As a more backend guy who does some frontend, the main thing I like about React over alternatives like Svelte, Vue and SolidJS is React Native. React is maybe not perfect for the web, but it’s very, very good, and it’s also quite good for mobile via React Native. The more purely web-focused libs/frameworks have far inferior (or no) mobile options, while other cross-platform frameworks, like Flutter, suck on the web.

Being able to use such similar concepts/knowledge for both web and mobile, with strong results in both places, that’s something React is uniquely good at (AFAIK), and a huge reason to choose it IMO.

People seem to say Quasar [0] (a framework on top of Vue, websites, PWAs, mobile, desktop) is great in that niche, but I can only say that their documentation looks good.

[0]: https://quasar.dev/

Interesting, have never played around with it. Is it just a WebView on mobile, though? What I like about React/React Native is that it’s web-native components on the web, mobile-native components on mobile, so you get true native look/feel/behaviour in both places. Too many of the alternatives are WebViews on mobile, basically just a web page embedded in an app. Or they do crazy things on the web, like Flutter turning your webpage into a giant canvas. React/React Native is the only popular/mature approach I’ve seen that embraces native components on both the web and mobile, though maybe there are others?
> Is it just a WebView on mobile, though?

Checked, yeah. Using Cordova or Capacitor. They say it looks native, though? No idea.

> What I like about React/React Native is that it’s web-native components on the web, mobile-native components on mobile, so you get true native look/feel/behaviour in both places.

Oh, that is cool. I never worked with anything mobile, so I didn’t know. I will read into that, not that I plan to use it, but it sounds interesting :D

Is React good on mobile or does it just have a good solution there? I don’t think anything is stopping vue-native from popping up other than interest and someone to work on it.
See my comment here with more about my take: https://news.ycombinator.com/item?id=35066431

But React/React Native is the only mature/popular web/mobile approach I’ve seen that embraces web components on the web AND mobile components on mobile, which I think is a big advantage. Though maybe there are others I’m unaware of!

I’m sure there could be React Native like solutions for other libs/frameworks, but I haven’t seen any that are as mature with the same “native components under the hood” approach.

TLDR: React Native sounds incredibly awesome until you are 5 years and 150 devs into it and realize that this shit sucks.

But hey, if you are under 10 people and need apps everywhere, it is a nice thing.

Yeah, if you have a big team, everyone is going to be specialized anyways. You can have:

- Dedicated Android devs working on your Java/Kotlin/whatever Android app

- Dedicated iOS devs working on your Swift/Objective-C/whatever iOS app

- Dedicated web devs working on your JS/TS/whatever web app

- Dedicated BE devs working on your BE services, in 1-many languages that may be none of the above

But for startups, that’s not gonna happen, there’s gonna be wayyyy fewer devs and wayyyy less specialization. A lot of companies will be in that mode for many years, possibly indefinitely. In those situations, React Native can be a big win. I’ve been working the past 2 years at a relatively small startup, ~10 devs, that’s TypeScript everywhere. We’ve got 2 mobile apps (mobility space, a Rider and Driver app), both TypeScript/React Native/MobX. Rider is iOS/Android/web, Driver iOS/Android, very nice having 2 apps instead of 5. Then a web-only admin app in TS/React/MobX, and backend services in TS/Express. Same language everywhere, and similar mental model across all FEs, is a big productivity boon at our size.

I'm using React Native to build mobile games, and I am pleasantly surprised I can just write my own state management and update logic (hack around states and props) to walk around a lot of issues and get good performance.
If you hack around the state management and update logic, what is React bringing to the table? Just the cross platform widgets?
Those same workarounds could be still be multi-platform (Android and iOS) and if you’ve got any sort of complexity in your business logic you don’t need to implement and test it in JS/TS + Swift + Kotlin, just JS/TS
Interesting, how are you drawing graphics? Skia?
Ionic gives you a solid base for mobile and the web with a slight bias towards mobile. It's all web components, no native renderers, but quite polished, because it's been around for a while. Imho, you can get quite far with it.
There is also https://svelte-native.technology/ (and I suspect similar projects for other frameworks) though I haven't used any of the "* Native"s
Ooh interesting! Similar to React Native in that it’s a JS interface to native components, didn’t know about this, worth a look!
When did you last use Flutter on the web? It has some quirks but it does not "suck" in my experience.
Basic react plus redux for state felt clean on the one React project I worked on years ago. Why do you need hooks and usememo?

Most of this article is a rant against the react hooks project, not React itself.

Things get more complicated when you start using React Context and start signalling updates in a parent component. The render cascades. Maybe one component fetches some data, some component remounts, and you run your state update again, delayed by a few seconds.

I'm not sure I'd ever expect a framework, React or anything else, to stop that behavior. If a child component signals to a parent that the state has changed then I would always expect that to cascade down the node tree. That could cause further updates. And more renders. That behavior is on me. If the framework decided not to cascade some updates that would be weird.

I think this highlights part of the problem with React and most other frameworks - people expect too much from them. If you're delegating all of your coding skill to the framework and expecting it to just magically work no matter what dodgy code design you throw at it then you're going to build a shitty app. You have to remember that you still have to think things through, use your skills as a dev, understand what's happening and why. That is always going to be true. You're always going to have to put the work in.

At the beginning of the article the author says they feel trapped by React because their previous, current, and next jobs are all going to be React based. That isn't true if they choose to put effort into learning other technologies and seeking roles that use them. If you work hard you find options open to you. Heck, they could move out of web and start writing completely different code that isn't even JS if they felt they wanted to. No one is being held hostage by React. You are only held hostage by your own fear of doing something hard. Feeling like you have to stick with React is a state of mind - you can change that with enough effort.

> I'm not sure I'd ever expect a framework, React or anything else, to stop that behavior.

Isn't this the whole selling point of Solid's signals? If a child component receives its props from the parent as signals, and asks the parent to fetch some data and update the state, then the child won't rerender; only the bits that are consuming the signals will. Fine-grained reactivity, they call it.

I saw signals in Preact and I thought the same.
The article goes into exactly this.
I've not used Solid much so I can't say, but my point is that if your app is rerendering unexpectedly that's because you haven't spend the time to think about the data flow around your app. It's possible, and not that hard even in a large app, to build things so that this doesn't happen. Signals sound like a way of avoiding updates, and if the experience of using them is elegant or if the performance is better that's awesome, but you definitely can build apps without them and never see the problem they solve.
> I'm not sure I'd ever expect a framework, React or anything else, to stop that behavior. If a child component signals to a parent that the state has changed then I would always expect that to cascade down the node tree. That could cause further updates. And more renders. That behavior is on me. If the framework decided not to cascade some updates that would be weird.

It's not that the properties shouldn't be updated it's that in React the whole subtree gets completely re-rendered, with a potentially big performance cost. Svelte just changes the relevant bit of the DOM, like a single class attribute or whatever, and leaves everything else be, this feature alone is what made me switch. In addition to baseline performance benefits certain things which are really awkward in React (e.g. animated transitions) become non-issues.

>Feeling like you have to stick with React is a state of mind - you can change that with enough effort.

I really appreciate your optimism about switching to a different framework/ etc. and I would have felt the same earlier in my career where I didn't have so many non work commitments, financial and otherwise. But to me now this reads as wishful thinking; switching track is difficult, especially when your existing skill set represents a large chunk of the demand in the marketplace. (And I say this having recently sucessfully made the switch from React to Svelte)

> switching track is difficult [...] (And I say this having recently sucessfully made the switch from React to Svelte)

Having developed with Angular and React, and dabbling with Vue, I have to say that Svelte has the best ergonomics of the lot, and the language tutorial is so approachable. I haven't had to think about performance or state to the degree that I have in other frameworks. Any workplace could easily skill up a Svelte dev from a React dev.

I really appreciate your optimism about switching to a different framework/ etc. and I would have felt the same earlier in my career where I didn't have so many non work commitments, financial and otherwise. But to me now this reads as wishful thinking; switching track is difficult, especially when your existing skill set represents a large chunk of the demand in the marketplace. (And I say this having recently sucessfully made the switch from React to Svelte)

No doubt there are individuals with circumstances that make switching tech stack harder due to the demands on their time elsewhere, and I feel for those devs being stuck on a stack they don't enjoy (I was a PHP dev for a decade, I understand their pain). But I also think that those problems are temporary. You might be stuck on something for a few years, but in the grand plan that is your career spending even a couple of hours a week to move to something that you don't hate is worthwhile.

It'd be awesome if everyone who dislikes React could spend a month immediately learning Svelte or Solid, or Kotlin or Swift, but that's obviously not possible. All I'm saying is that if you're not doing anything to change your future then you should seriously consider if the problem is as bad as you might say it is.

> Svelte just changes the relevant bit of the DOM,

Because Svelte is mutable state galore. I thought we all agreed to say no thanks to that.

Yeah, but atleast in Svelte it's explicit, and you can if you wish write svelte as if ste were immutable. Anecdotal, but still, I've had fewer bugs (particularly wierd UI glitches) in Svelte than I ever did in React. I just like Svelte for the types of project I work on.

Tangent: the idea that "we all agreed to say no thanks to that" is kind of symptomatic of broader issues I have with web dev. i.e. that there's very little recognition that different tools have different uses and knowing when to pick which is part of the job. Working with wood you wouldn't apply the same practices and methods to building the timber frame of 2 story house as you would to making an intricately carved toy elephant. Why when working with the materials of the web, HTML/CSS/JS, do we assume there's a best and right why to do it: "you must write tests!", "avoid using z-index!", "separate content and form", "immutable state!"; these are all the right answer in some situation and not in others.

> If you're delegating all of your coding skill to the framework and expecting it to just magically work no matter what dodgy code design you throw at it then you're going to build a shitty app.

Not to disagreed with you here, but there are many frameworks out there which either claiming themselves as "full-stack" or trying to be as full-stack as possible.

The developers who uses these frameworks might just expect "(delegating your code to the framework) is how it suppose to be used"(, while blaming people who write "raw" JavaScript code as "hacky").

This is a problem which will occur whenever you want to standardize the workflow as well as the knowledge base for your team. Some approach is discarded in this process and what's left in the end are often "common practices" which nobody has reason to reject. If the "common practices" is to let the framework to do it, then that will be that.

It will be interesting to see whether the React Forget compiler (https://reactjs.org/blog/2022/06/15/react-labs-what-we-have-...) will change any of this. I'm curious how this will turn out to work, and if it will remove some of the issues that tend to confuse and annoy people.

My own impression is that the core model of state and rerendering is actually quite nice and intuitive, though often explained a bit wrong. The part that makes it complex and confusing are things like callbacks, which can trigger lots of unnecessary rerendering and force quite some boilerplate if you want to avoid that. If you can remove all the stuff around trying to avoid rerendering unnecessarily, React would be a lot simpler.

I also think that people are too quick to use the wrong tools for managing state in React, e.g. Context to avoid a bit of prop drilling.

This post follows the current trend hyping up signals, but glosses over the complexity they bring.

We can agree that state management is complex, no matter how it’s done. If you disagree, cool go build a database.

Of all the complexities around state management, the one squarely placed at the top for me is: time.

State is a variable you care about, that will change over time.

Signals and Hooks/Effects present two very different approaches to the problem.

They both require updating your mental model, and they both have specialised tooling.

Myself, I’ve never fully grokked observables/signals—particularly in relation to a UI. They shift complexity into a location that I think makes them harder to reason about.

I did take to the React approach with Components and hooks. And in my experience so did many others.

I disagree with the article saying all frameworks must have signals, and I appreciate the React core team holding their ground on that.

It’s healthy for the ecosystem to have frameworks built on different ideas, otherwise why build a new framework?

But React, if you added signals I think you would warp it’s entire foundational paradigm.