> Overall, though, the use of a true MVC UI framework seemed like a great step forward
The author keeps saying 'MVC' as if it ever made any sense in the context of React. The old react docs used to quip that react was the v of mvc, until this notion was scraped entirely; and although one might perhaps suggest that props and templating is a v, and state is conceivably an m, there has never been anything concrete one could point out and argue that it is a c.
You have your model (data), and conceptually, you just want to bind that model to the view. But you have to write all this imperative code to do that. It's very simple with an imperative UI to have infinite loops even with very simple UIs. "When this field changes, I want to update this other field". But that other field has it's own event listeners that trigger other effects. The event listeners work fine in their own silo, but the interactions between fields cause unintended effects that are not obvious reading the code.
When the component is mounted, the behavior is very hard to reason about and you spend lots of time in a debugger tracing through all the event listeners just to reach the initial state of the UI. Additionally, in these frameworks the developer is typically responsible for cleaning up all the event listeners. It's very easy to forget to clean these up properly.
Once a UI reaches a certain complexity, you try to rewrite the imperative code so that it almost reads declarative and you wish you could simply use a declarative UI framework. I can't speak for React as I have not used that in a long time, but in Vue.js I never write the UI to use global state. All state is local to the views that it pertains to and with defineModel introduced back in late 2023, you can write small UI components without all the plumbing required in earlier versions. I've never experienced such a simple and reliable UI framework previously.
I think a logical continuation of this model is something like Solid.js, where there is no concept of re-rendering, just atomic DOM updates when observables change their values, but somehow this approach didn't get critical traction.
And sorry, but, it was a complete mess from start to finish. Instead of just mapping a boolean value to a state, the entire read and write path was this elaborate game of telephone. In React I would just use something like a cursor to traverse and mutate state immutably, and the rendering part would take care of itself. There was also a bunch of extra code to remember and apply defaults, which in a more functional system like React is generally managed via composition.
One of the article's claims is that the React model is suboptimal because UIs are more stable than it assumes. But this isn't true because the edge cases is what you will end up spending the most dev time on.
A declarative approach lets you achieve N features in mostly O(n) lines of code. When you do things imperatively, you're instead having to orchestrate up to O(n^2) state transitions in O(n^2) lines of code.
The React model is also not that different from immediate mode, which is very popular in games, where performance is important. The main difference is that React has an answer to what happens when you can't fit all the work into one rendering cycle, via memoization and sparse updates.
This gets you similar perf to classic retained mode, but without all the tedious MVC plumbing.
PS: Here's how i use patching as a basis for state management, https://usegpu.live/docs/reference-live-@use-gpu-state