> 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.
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.
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.
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.
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.