I'm starting to wonder whether reactivity (not React specifically) was the originally sin that led to modern UI complexity. UI elements automatically reacting to data changes (as oppposed to components updating themselves by listening to events) was supposed to make things easier. But in reality, it introduced state as something distinct from both the UI and the data source (usually an API or a local cache). That introduced state management. It was all downhill from there (starting with two way data binding, Flux architecture, Redux, state vs. props, sagas, prop drilling, hooks, context API, stateful components vs. stateless components, immutability, shallow copy vs. deep copy, so on and so forth).
neya 9 hours ago [-]
Absolutely. Look at facebook today. Back in 2010, everything had just the right amount of interactivity. Because, separation of concerns existed at the language level - HTML for structure and CSS for presentation, JS for everything else.
Then some bunch of geniuses decided it would be awesome to put everything together in the name of components. Today, you open facebook, the creators of React - normal drop-down with just a list of barely 5-6 items is a fucking component that makes 10 different requests. I would even argue this unnecessary forced interactivity is what perhaps annoyed users the most as everything always has to "load" with a spinner to the point of the platform being unusable.
Same goes for instagram. It's not just that, React is a hot ball of mess. It's not opinionated, so anyone can use anything to do anything. This means if you work with multiple teams, each one uses their own code organisation, state management library and general coding paradigm. Eventually the engineers leave and the new guy decides to do things his own way. I've honestly never seen a company with a great product run over React. Everything always is being re-written, migrated every 3 weeks or straight up is buggy or doesn't work.
React is the worst thing to happen to the Javascript ecosystem. The idea is good, but the execution is just piss poor. I mean look at Vue and Svelte, they managed to do it right.
incrudible 4 hours ago [-]
If the html+css+js trifecta was any good for creating UI beyond simple forms, we would not have witnessed the cambrian explosion of ways to do it differently. Reactivity itself was an answer to the pain of using MVC and similar approaches in older GUI toolkits not made for the web. The pain did not stop entirely, of course, because GUI is a complicated and ill defined problem - but I don’t look back fondly to programming without it.
usrbinenv 49 minutes ago [-]
React got popular not because of its amazing time-tested ideas (everyone knows they re-engineer everything once every couple years!), but, strictly speaking, because at the time it was released there wasn't any kind of serious SPA or partially-SPA framework for the web and also because JavaScript sucked a lot more at the time (no classes!). Qite is perfectly suitable for complex UIs thanks to its state functionality, you can build pretty complex functionality and UI and not sacrifice user's CPU in the process.
applfanboysbgon 10 hours ago [-]
I genuinely don't understand why this model is the norm. As a game developer working in my own engine, UI is unbelievably straight-forward: the game has state. The master Render() function draws all of the graphics according to the current state, called at framerate times per second. Nothing in Render() can change the state of the program. The program can be run headlessly with Render() pre-processed out completely. The mental model is so easy to work with. There is a sleep-management routine to save on CPU usage when idle, and dirty logic to avoid re-drawing static content constantly. I feel like the world would save 90% of its GUI development time if it didn't do whatever the fuck reactive UIs are doing.
sureglymop 3 minutes ago [-]
This made me immediately think of the Elm architecture.
To an extent this is how react works internally. There is a function which takes state and produces UI. In order not to have to re-render the whole UI if only a small part of the state changes, there is a diffing algorithm and "virtual dom" that is diffed against. Maybe it doesn't work exactly like that anymore but that's the gist of it.
scoopdewoop 8 hours ago [-]
That is immediate-mode graphics. Fine when you are already power-budgeted for 60 frames each second. UIs typically use retained-mode graphics, with persisting regions.
pier25 5 hours ago [-]
Games can afford the luxury to re-render everyting on every frame. The DOM? Not so much.
This bottleneck could be alleviated if browsers shipped native dom morphing or even some kind of native vdom but we're stuck with userland js solutions.
chill1234 9 hours ago [-]
Isn't that what reactive ui trying to achieve? To only have a render function and have ui state sync according to the data?
incrudible 4 hours ago [-]
Games do not sync data, they literally say what should be drawn on the screen, from scratch, 60+ times per second. They are in control of the entire process. They do not need to deal with DOM manipulation overhead because there is no DOM.
monarchwadia 6 hours ago [-]
Well, in React specifically, you're describing the Flux architecture, which I've implemented manually back in the day. Its modern-day successor is Redux, which does exactly what you describe, but we found that it introduced more complexity rather than remove it.
I don't know about the other UIs, but on the web, some things impinge on the model you (and Redux) are proposing.
One thing is: you, in the gamedev world, have the luxury of having a frame buffer to write to. You fully control what gets rendered. Unfortunately, React and its cousins all have to deal with the idiosyncracies of the legacy browser environment. You have CSS, which applies and cascades styles to elements and their children in often non-obvious ways, and is a monster to deal with on any given day.
In addition to CSS, you have multiple potential sources of state. Every HTML slider, dropdown, input field, accordion, radio button, checkbox has its own browser-native state. You have to control for that.
On top of all of this, the browser application is usually just a frontend client that has to interact with a backend server, with asynchronous calls that require wait-state and failure-state management.
One thing that's in common with all of the above problems is: they're localized. All of these things I'm describing are specific to the rendering layer and therefore the component layer; they are not related to central state. A central state trying to capture all of these problems will fail, because component state has to be wrangled locally near where the HTML is; CSS also is component-level; and the network states are often very closely related to each component. If we maintain a central "game state", the data complexity just proliferates endlessly for each instance of the component.
So, the default these days is to keep state very close to each component, including network state, and often business logic also gets sucked into the mix. I try to avoid putting business logic in components, but people do it all the time unfortunately. But it does add to the complexity.
In other words, there is -real- complexity here, stemming from the fact that the web was never built to be a distribution+execution layer for rich applications, but evolved to become exactly that. It's not just bad application architecture or bad decisions by React maintainers.
Maybe I'm wrong, since I'm not a game developer and don't see what you're seeing on your side.
applfanboysbgon 5 hours ago [-]
I'm sympathetic to "it's the browser's fault", to some degree. I understand that the browser locks you into certain constraints, and I understand that I don't understand much about those constraints, because most of the extent of my experience with web development is using a canvas and a couple of fundamental APIs to render my games via WASM as web is one of my build targets (and I do know that approach is undesirable for regular web pages). I can see how there might be unavoidable complexity there.
What I still don't understand is why the browser is that way in the first place, and why all of the native, not-browser GUI frameworks that people use are also that way. People opt into using React Native, even! But the regular run-of-the-mill frameworks that are widely used for native applications are also annoyingly complex to work with, so much so that I've repurposed my engine for when I want to create native applications and have been working on building a desktop UI framework within it that follows the same model I use for games (albeit nowhere near production-grade, just covering "the cases I need").
> the browser application is usually just a frontend client that has to interact with a backend server
I will note that this is a constraint that is shared with gamedev. Most multiplayer and even many singleplayer games these days are server-based.
9 hours ago [-]
tmanderson 3 hours ago [-]
lol this is why so many game UIs are awful (how much they lack in terms of OS accessibility, keyboard controls/shortcuts, etc)
cjonas 7 hours ago [-]
This is basically "reactive UI" foundation. The complexities come from effects (now managed via hooks)
wonnage 41 minutes ago [-]
Congrats, you described imgui which is basically react
hliyan 10 hours ago [-]
That reminded me of another complexity: virtual DOM diff.
croes 10 hours ago [-]
UI is mostly static.
Rendering everything at framerate per second is a huge waste of time and energy.
Lerc 9 hours ago [-]
This was the case back in the days of the Amiga and 68000 Macs. Rendering everything every frame was impossible, the only way to make it work at all was to draw only what was absolutely necessary to depict changes.
Then computers got faster, much much faster. It became possible to redraw the whole UI from state every frame without it being a significant cost.
At the same time retained user interfaces managed to become more and more costly to do just about anything. I don't think for any particular reason other than computers were fast and they didn't need to do much better.
I find it really odd that there are user interfaces that take longer to rearrange their items than it takes for the same CPU to RayTrace a scene covering the same amount of screen area.
croes 9 hours ago [-]
Just because computer got much faster doesn’t mean it’s a good idea to make wasteful rerenderings of things that didn’t change.
Lerc 9 hours ago [-]
No but calculation becoming more efficient than recall might not make it a good idea to make wasteful fetches.
croes 9 hours ago [-]
Nothing id more effective than doing nothing.
potsandpans 2 hours ago [-]
> I genuinely don't understand why this model is the norm. As a game developer working in my own engine, UI is unbelievably straight-forwar
I can't really think of a statement that resonates with me less.
mpalmer 10 hours ago [-]
[flagged]
applfanboysbgon 9 hours ago [-]
Indeed, I genuinely do not. Rather than passive-aggressively insulting my intelligence, why not explain it for me? As I understand it, React was an attempt to shoehorn "immediate-mode UI"[1] on top of retained-mode UI, so it seems like web developers do in fact want to build immediate-mode UIs, and in fact are constantly complaining about the nightmarish complexity of the status quo.
[1] I loathe this term, by the way. It's one of those terms that, I think, belong to a discipline of developers who love to obfuscate everything, even simple concepts, with unnecessarily opaque terminology until nobody can understand what the hell anyone is talking about anymore.
bryanrasmussen 9 hours ago [-]
>As I understand it, React was an attempt to shoehorn "immediate-mode UI"[1] on top of retained-mode UI
the problem is that the typical modern web page is considered as a combination of immediate-mode and retained-mode.
therefore, as it is wasteful to update all the page when only a few components on the page change, people want to only update parts of the page immediately when changes happen.
furthermore the typical modern web page only makes sense in the context of the modern web site, so some pages are almost everything on the page needs to update all the time, some pages are nothing here needs to update until the user does anything, some pages are nothing here needs to update at all, and other pages are just a couple components need to update all the time based on various things.
This context of what a web site is like is very much determined by the type of the site, where many e-commerce sites are affected by all sorts of data that occur outside of whatever page the user is on and need to update all sorts of different components on a page, many governmental sites are almost just static, with all sorts of variations in between.
cluckindan 9 hours ago [-]
Which part of a web page is immediate mode, exactly?
Maybe <canvas> if you clear it on every frame.
bryanrasmussen 4 hours ago [-]
I was just responding to the usage that the parent commenter had which was
>As I understand it, React was an attempt to shoehorn "immediate-mode UI"[1] on top of retained-mode UI
which I interpreted as the only possible meaning, in relation to React, being UI components that must rerender as close to immediately as possible vs. UI components that do not need immediate rerendering when the underlying data has changed.
I realize that is not a particularly correct use of the phrases, but then that is what happens when you use a concept from one type of development metaphorically in another type of development, memetic slippage as it were.
never_inline 9 hours ago [-]
I am no web developer but whenever I built the UIs, re-rendering a page by doing some big DOM change through JS as always led to stutter. So maybe its just inefficient and can't be optimised.
cluckindan 9 hours ago [-]
React is not immediate-mode in the traditional sense where everything is redrawn on every frame.
user34283 9 hours ago [-]
On the web you need accessibility and often also responsive layouts.
These are requirements the DOM / CSSOM addresses, you'd probably not have an easy time getting this right in a <canvas>.
cindyllm 8 hours ago [-]
[dead]
mpalmer 9 hours ago [-]
[flagged]
spoiler 9 hours ago [-]
No horse in this race, but your phrasing seems a bit weird, honestly... If reduced, your comments read as:
"You don't know about X? Well, at least I know about X and Y..." Doesn't seemed like a good faith comment to me either?
And then you say "You misunderstood my intentions so I'm going to disengage". For what it's worth, I didn't interpret your argument as insulting someone, but also it wasn't a useful or productive comment either.
What did you hope to achieve with your comments? Was it simply to state how you know something the other person doesn't? What purpose do you think that serves here?
applfanboysbgon 9 hours ago [-]
I guess I misinterpreted your comment? I do apologise if that's the case. I certainly didn't intend to "jump down your throat", I was asking you to explain your comment further because I don't understand what you're getting at.
mpalmer 9 hours ago [-]
To be perfectly fair, you accused me of insulting you and said you "loathe" a word which I thought was a fairly inert term of art. Would you believe I didn't actually notice that you wanted me to say more? :) More than happy to give the benefit of the doubt though, the shoe's been on the other foot for me more than once.
For my part, I also loathe the insensate writhing mass of frameworks, patterns and dependencies that is "modern" frontend development. Where you and I differ is I recognize a handful of extremely good ideas hidden in the morass. But I am perfectly happy dismissing the majority of it; if nothing else, you shouldn't come away thinking of me as a React fanboy.
Writing is a lossy medium for thought, and programming is no exception. I'd say at a minimum that you and I are on the side of programmers whose code is a medium for their own thought.
All of these choices really just comes down to cognitive bandwidth, context, domain, taste, any number of things, really. Which is what was behind my first (admittedly terse, slightly salty) comment.
What I condemn is someone who opts out of making choices for themselves in their software. Web dev just happens to have an unfortunately high concentration of this sort of thoughtlessness.
whstl 9 hours ago [-]
> The master Render() function draws all of the graphics according to the current state
What you are describing is exactly what GP complained about: "state as something distinct from both the UI and the data source".
React can be 100% stateless, functional, and have the state live somewhere else. You just need to apply the same limitations as your model: components should be simple and not store data in themselves.
This is why people came up with things like Flux/Redux/Reducers/Immutability, to handle this in a standardized way, but nothing is necessary.
cluckindan 9 hours ago [-]
>components should be simple and not store data in themselves.
That is a ”controlled component” model which is bad for interactivity, especially text inputs.
If every keypress triggers a state change and rerender, the UI will be slow and things like focus management become complex issues.
Without a rerender, it must now use a reactive binding to update the field value.
If you don’t want to update state on every keypress, your component must be uncontrolled, store its state internally (in the DOM) and update it to a parent store e.g. when the user stops typing (debounced) or moves focus out of the field. These are not trivial things either, and as a result, components get more boilerplate to handle the UX complexity. And of course, there are now UX pitfalls.
Indeed, these are reasons why reactive patterns exist. Now, if they just managed to abstract away the tedium.
Izkata 8 hours ago [-]
I don't know what people generally recommend now, but for a long time the best practices with organizing React components had them connected to the store midway down the tree or higher, which definitely would have contributed to the UI slowness since it would rerender everything below that on each update. Push the store access down as far into the leaves as possible and you won't get anything noticeable, even though it is still doing more work than just accessing the DOM state as needed.
Also, focus management isn't really a thing in React, the vdom diffing means DOM nodes are updated instead of replaced so focus isn't lost or changed unexpectedly. There used to be a demo on the React homepage showing this, since the idea was very new to most people at the time - everything popular before it was just rendering template fragments to replace nodes and did have this problem.
cluckindan 6 hours ago [-]
Focus management is absolutely a thing in React if you plan to be ADA or WCAG compliant, even if it’s not needed for text inputs.
9 hours ago [-]
codethief 8 hours ago [-]
> React can be 100% stateless, functional, and have the state live somewhere else. You just need to apply the same limitations as your model: components should be simple and not store data in themselves.
"just" is doing a lot of heavy lifting here. Where do you store "pure" GUI state (button state, is expandable expanded, …)? Do you really want to setup Redux for this? (And no, the DOM is not an option in non-trivial cases.)
Jenk 7 hours ago [-]
Might be naive, but this has always been a concern of the view-model for me. Every GUI change results in a VM change via event/command. The VM becomes gospel for UI state which means reducers are much simpler, and my actual model doesn't care if it is indeed a button, expando, radio button or whatever else.
whstl 6 hours ago [-]
I'm not defending this model anywhere. I'm just stating that React can do what applfanboysbgon suggested: "As a game developer working in my own engine, UI is unbelievably straight-forward: [...]"
bikeshaving 1 hours ago [-]
I’ve written about how Svelte, Vue, and Solid are all reactive and share common pitfalls due to their reactive solutions. My theory is that they all cause worse bugs than they prevent.
I'd argue that it was all downhill after we moved away from using HTML as the state representation.
Moving state out of HTML and into JS means we now have to walk this ridiculous tightrope walk trying to force state changes back into the DOM and our styles to keep everything in sync.
Given that problem, reactivity isn't the worst solution in my opinion. It tries to automate that syncing problem with tooling and convention, usually declaratively.
If I had to do it all again though, DOM would still be the source of truth and any custom components in JS would always be working with DOM directly. Custom elements are a great fit for that approach if you stick to using them for basic lifecycle hooks, events, and attribute getters/setters.
pfraze 5 hours ago [-]
Wasn’t that the Lit framework? It was okay. Like a slightly more irritating version of React.
I recall the property passing model being a nasty abstraction breaker. HTML attributes are all strings, so if you wanted to pass objects or functions to children you had to do that via “props” instead of “attributes.”
I also recall the tag names of web components being a pain. Always need a dash, always need to be registered.
None of these problems broke it; they just made it irritating by comparison. There wasn’t really much upside either. No real performance gain or superior feature, and you got fewer features and a smaller ecosystem.
spankalee 5 hours ago [-]
The point of Lit is not to compete with React itself, but to build interoperable web components. If your app (Hi Beaker!) is only using one library/framework, and will only ever one one in eternity, then interoperability might not be a big concern. But if you're building components for multiple teams, mixing components from multiple teams, or ever deal with migrations, then interoperability might be hugely important.
Even so, Lit is widely used to build very complex apps (Beaker, as you know, Photoshop, Reddit, Home Assistant, Microsoft App Store, SpaceX things, ...).
Property bindings are just as ergonomic as attributes with the .foo= syntax, and tag name declaration has rarely come up as a big friction point, especially with the declarative @customElement() decorator. The rest is indeed like a faster less proprietary React in many ways.
_heimdall 3 hours ago [-]
Kind of? Lit does add some of the types of patterns I'm talking about but they add a lot more as well. I always avoided it due to the heavy use of typescript decorators required to get a decent DX, the framework is pretty opinionated on your build system in my experience.
I also didn't often see Lit being used in a way that stuck to the idea that the DOM should be your state. That could very well be because most web devs are coming to it with a background in react or similar, but when I did see Lit used it often involved a heavy use of in-memory state tracked inside of components and never making it into the DOM.
pfraze 5 hours ago [-]
Dont get me wrong, I'm a pretty big believer in interop, but in practice I've rarely run into a situation where I need to mix components from multiple frameworks. Especially because React is so dominant.
spankalee 5 hours ago [-]
HTML simply can't represent the complex state of real apps. Moving state to HTML actually means keeping the state on the server and not representing it very well on the client.
That's an ok choice in some cases, but the web clearly moved on from that to be able to have richer interaction, and in a lot of cases, much easier development.
_heimdall 3 hours ago [-]
I'm sure you could find examples to prove me wrong here so I'm definitely not saying this is a hard line, but I've always found that if app state is too complex to represent in the UI or isn't needed in the UI at all, that's state that belongs on the back end rather than the frontend.
My usual go-to rule is that business logic belongs where the state lives - almost always on the back end for state of any real complexity.
With true web apps like Figma I consider those entirely different use cases. They're really building what amounts to a native app that leverage the web as a distribution platform, it has nothing to do with HTML at all really.
wonnage 39 minutes ago [-]
State in HTML is a horrible mistake. Now everything has to be constantly serialized/deserialized into strings.
usrbinenv 34 minutes ago [-]
It's a bit more nuanced than that. State in Qite is held both in HTML and in JS Component. The html serialization is sort of consequence of changing a field (like when you want to update textarea content, for example). You can completely ignore it or you can also use it for CSS, for example. Another usecase is when user interacts with the pages, changes text in said textarea and it also automatically updates the JS Component field. Finally, there are also flags, which aren't stored in DOM. I'd like to point out this architecture isn't random, it came from building apps and realizing how everything interacts.
pier25 5 hours ago [-]
> I'm starting to wonder whether reactivity (not React specifically) was the originally sin that led to modern UI complexity
I've always maintained that no reactivity is a much simpler mental model. Mithril and Imba do this with better than good enough performance.
I think Remix 3 will be following this approach too.
olivermuty 4 hours ago [-]
Is this a satire thing or will it really be remix3? Didnt they just rebrand to react router FROM remix??
pier25 4 hours ago [-]
No, I'm serious.
The previous Remix was rebranded into React Router. Remix 3 will not use React and will apparently not use reactivity either.
I use Preact without reactivity. That way we can have familiar components that look like React (including strong typing, Typescript / TSX), server-side rendering and still have explicit render calls using an MVC pattern.
yde_java 10 hours ago [-]
How and when do your components update in such an architecture?
tobyhinloopen 8 hours ago [-]
View triggers an event -> Controller receives event, updating the model as it sees fit -> Controller calls render to update views
Model knows nothing about controller or views, so they're independently testable. Models and views are composed of a tree of entities (model) and components (views). Controller is the glue. Also, API calls are done by the controller.
So it is more of an Entity-Boundary-Control pattern.
gr4vityWall 9 hours ago [-]
From what I can tell, they do full page reloads when visiting a different page, and use Preact for building UIs using components. Those components and pages then get rendered on the server as typical template engines.
ivanjermakov 10 hours ago [-]
I still believe immediate rendering is the only way for easy-to-reason-about UI building. And I believe this is why early React took off - a set of simple functions that take state and output page layout. Too bad DOM architecture is not compatible with direct immediate rendering. Shadow DOM or tree diffing shenanigans under the hood are needed.
pfraze 6 hours ago [-]
Reactivity isn’t the problem. Reactivity is one of the few things that helps reduce the complexity of state management. GUI state is just a complex thing. Frontend development doesn’t get enough cred for how deeply difficult it is.
rglover 7 hours ago [-]
Yep. It's one of those great on paper, tough in reality models. Used sparingly and wisely, it can make great UX fairly trivial. But sadly, state is more often abused and loaded with tons of data and complexity it shouldn't be holding. Something, something just because you can, doesn't mean you should.
speefers 7 hours ago [-]
[dead]
codethief 8 hours ago [-]
> UI elements automatically reacting to data changes (as oppposed to components updating themselves by listening to events)
Is there really a difference? Angular uses RxJS in a pub-sub scheme. (At least it did when I last used it.)
dminik 7 hours ago [-]
It's much simpler. Reactive UIs and declarative UIs let you built things more more easily. You can almost entirely ignore an entire class of issues (state mismatch for instance).
That of course led to developers building much more complex UIs. Which offset the gains from reactivity. Hence the mess and we're basically where we started.
ramesh31 8 hours ago [-]
Give me state management vs. event bus management any day of the week. The former is fully testable and verifiable. You can even formally define your UI as a state machine. With events you are constantly chasing down race conditions and edge cases, and if your data lives seperately in components there is no clean way to share it horizontally.
usrbinenv 57 minutes ago [-]
Just to clarify: Qite does both events AND state, which I find quite powerful and useful.
AlienRobot 8 hours ago [-]
In my view, the problem isn't specifically reactivity but the fact that reactivity isn't actually native of the UI toolkit.
Instead of HTML, think about GTK or Swing.
To add React-style "reactivity" to it, instead of just making a dialog to change the "title" of a document and committing the change when you press OK, you'd need a top-level "App" class that holds all the state, a class for state properties with IDs accessible at runtime which probably would be a variant (accepts any primitive type), a binding class to bind the toolkit's textbox to the App's state "title" property (because you'll probably want to bind a lot of textboxes, so it's easier to separate the code into classes), and then every time the user types something into the textbox, instead of using the toolkit's code that is already written for you which updates the textbox' state directly, you block the state change in an event handler, send the state change to the App class, let the App class figure out the differences between the current state and the new state, and then it calls some callback in the binding class that is responsible for actually changing the text in the textbox to reflect the new App state. You'll probably run into a ton of issues (selections resetting, assistive technologies bugging, etc.) that you'll have to deal with externally somehow. All just to make it do exactly the same thing it would have done anyway.
It's like you have a fully autonomous robot and you want to add marionette strings to make it move.
nogridbag 5 hours ago [-]
I believe every UI developer that has used frameworks like Swing has reached a point where specific user interfaces, even those that look trivial, become too complex primarily due to things like event handlers. Trying to figure out a simple thing like why a radio box is enabled and is marked dirty may require long debugging sessions where one event handler for component A triggers another event handler for component B, which triggers another event handler, etc. And before you know it, 50 events were triggered just during the initial mounting of the UI. Making sense of it all is maddening.
And then said developer does what they think feels right: "I have my state and I simply want all the fields to reflect my state". So they try and rewrite the component into some sort of mini immediate-mode style component. All of the event handlers get wired up a single "layoutComponent" method that tries to call all the UI component setters based on the current state with all the problems you alluded to. I know I've done this type of things numerous times before going back all the way to my first internship, well before React was even a thing.
I think modern frameworks solve the reactivity issue this well enough, that it really doesn't matter if the underlying framework is not natively reactive. I will say though that I've primarily used Vue.js where most state is relatively local and we don't try to re-render the world on every input. I think part of the problem with modern dev is likely that React has become the default instead of a simpler framework like Vue.
AlienRobot 3 hours ago [-]
That's true. Events are the WORST thing about GUI programming. They're so convenient and so undebuggable it almost feels like a trap.
Ironically, in most cases events are only used by one object, but you always want to consider the possibility that two objects will want to observe the same event, so now you need an entire event dispatching class, and then you'll want observable properties, and the nail on the coffin is going to be observable lists. When you reach that point, one event triggers another, which changes a property, triggering another event, and so on and so on. You are 5 layers deep into event callbacks. The call tree just has the same "callCallbacks()" method over and over again.
Bugs start happening because of the order in which callbacks are called becomes important, so now you need a way to give some callbacks priority over others, or make them happen after all normal callbacks were called. One callback destroys an object which has callback on the event that destroyed it, so you're going to need a wrapper around your callbacks that gets notified when callback's object is destroyed to change its reference to null in order to avoid executing code on the destroyed object if this happens while iterating the callbacks in the event dispatcher. Sometimes calling callbacks in wrong order is a performance hit, when it doesn't just get stuck into an infinite loop and you run out of stack.
I wonder if there is GUI programming paradigm that solves all of this or that you can call the "best" one. Maybe it's reactivity, maybe not. Who knows.
mpalmer 10 hours ago [-]
Why do you list all of these design patterns as though you have to hold them all in your head at the same time? As though each one made the ecosystem successively worse?
UI elements automatically reacting to data changes (as oppposed to components updating themselves by listening to events)
That's not so much a lack of statefulness as it is making zero effort to lift your application's data model out of platform-specific UI concerns.
The "isPresent()" in the example gives me alot of ick. It's confusing why thats not actual javascript.
usrbinenv 26 minutes ago [-]
Btw, looking back at the index page, I think I might have made the initial example a little bit too much (because realistically, you don't often get components that complex). If you guys want a simpler saner example, the one the second page looks nicer: https://qitejs.qount25.dev/Explained-by-ducks.html
QubridAI 14 minutes ago [-]
Feels like a refreshing “back to basics” take if it keeps things simple without sacrificing power, there’s definitely an audience for it.
voidUpdate 8 hours ago [-]
At some point, someone is going to come out with a no-JS, no-NPM, no-SSR framework and we're just going to have invented HTML again
Why have `<div data-part="form">` instead of using a `<form>` element?
usrbinenv 1 hours ago [-]
You can have <form data-part="form"> too. The tag doesn't matter. The data-component, data-roles, data-part or data-field attributes is what makes your HTML be a component, a component part or a field in Qite.
zhisme 8 hours ago [-]
this! it is absolutely nuts having everything in div/span elements and then assigning data/class attributes so they could behave like form or any other interactable element..
Oh my. If it works just like Ajax from >10-15 years ago, then I will be super happy. :D
usrbinenv 40 minutes ago [-]
It works better than "just like" in the sense that it also takes care of things like CSRF, POST/GET params, request/response types etc for basically free.
johnisgood 37 minutes ago [-]
Fair enough. Even better!
egeozcan 11 hours ago [-]
IMHO, you shouldn't make "hate" part of your tagline.
Maybe focus on a use-case? Something like, "No-build, no-NPM, SSR-first JavaScript framework specializing in Time-to-interactive" - maybe?
yde_java 9 hours ago [-]
Why self-censoring for using "hate" when it gets the message across quickly? Everyone understands that we use "hate" and "love" with huge levels of nuances. I personally said today to a colleague "I hate working from home" but it's clear that I'm not a racist against people who "love" remote work. We do work with a very lax work-from-philosophy.
tkzed49 1 hours ago [-]
from my perspective--I have to use React, Lit, and all kinds of other creative solutions at my day job--I'm going to immediately devalue someone's argument if it starts with "I hate React".
React is not popular simply because engineers hate themselves or enjoy pain. There are problems it solves, and problems it creates. Explain what problems your solution solves, and feel free to dunk on React while you're at it, but write a tagline like this and I'm not gonna take you seriously.
iammrpayments 5 hours ago [-]
This just sounds like every js framework that comes out every week and would never get as much attention. OP just did something marketers call “positioning” right.
56 minutes ago [-]
ale 11 hours ago [-]
Build steps are realistically speaking inevitable because of minification, tree-shaking, etc. which is not even a big deal these days with tools like esbuild. For a "true" DOM-first component reactive system just use Web Components and any Signals library out there and you're good.
xgulfie 10 hours ago [-]
But build steps suck
febusravenga 11 hours ago [-]
"If you hate react" feels like very bad argument in engineering.
Anyway, interesting approach for up to medium pages (not apps!). Totally not replacement for react.
anematode 11 hours ago [-]
Perhaps a bad argument, but for some people a very compelling one...
broken-kebab 4 hours ago [-]
One meaning people often use 'hate' word for is discomfort. It's often very subjective but it's not necessary a bad argument.
austin-cheney 11 hours ago [-]
Why is that a bad argument? The author strongly dislikes React and so wrote an alternative that is radically more simple, which sounds like a perfectly sane argument.
bestest 11 hours ago [-]
Does the author dislike react? How about preact? Or maybe simply jsx? Or nextjs?
There's nothing wrong with either of these if used correctly. Thus "hate" is a rather shallow argument.
johnisgood 39 minutes ago [-]
"hate" is not even an argument. It is obviously for those who dislike React or put it in another way: do not like to or would rather not work with React.
tobr 10 hours ago [-]
Your argument that it’s a shallow argument is itself a shallow argument. ”I hate x” is not a technical argument anyway, it’s an emotional assessment.
mexicocitinluez 54 minutes ago [-]
But they're shilling a technical solution not an emotional one.
usrbinenv 43 minutes ago [-]
As much as we like to think of ourselves as rational beings, emotions are still a very large part of our decision making process. I didn't build Qite because I hate React, I built it because I knew exactly how I wanted things to work. But I do hate React and it's part of why I knew exactly how I wanted things to work.
austin-cheney 8 hours ago [-]
I will safely assume the author dislikes all that overly complex bloat bullshit and leave it at that. I am not going to autism this, as in invent a bunch of straw men to attack because there is some singular obsession silo of react-like fixations.
imtringued 7 hours ago [-]
Calling preact bloated is pretty bold.
corstian 10 hours ago [-]
[dead]
rsmtjohn 7 hours ago [-]
I have been building with Next.js for years and still reach for it by default, but I genuinely appreciate the philosophy here. The no-build approach eliminates an entire class of problems -- stale caches, bundler config drift, slow CI pipelines -- that we have collectively normalized as "just how frontend works."
The SSR-first angle is especially interesting. Most frameworks bolt on SSR as an afterthought. Starting from HTML and progressively enhancing is how the web was designed to work, and it is telling that we keep circling back to it.
esperent 7 hours ago [-]
I've been building out a fairly complex app. I decided to avoid Next.js some I went with a simple Hono + Tanstack Router/query. With Vite 8, my build time is about ~0.8s.
I've also go a much simpler Next.js app with a build time of 45s.
steve_adams_86 41 minutes ago [-]
That stack is such a breath of fresh air. And so easy to deploy anywhere.
I do love the idea of a batteries included framework for the JS ecosystem, like the mythical Rails for node, but as long as we're gluing random stuff together... This is a really nice combo. I also love using Hono and React/Vite with TRPC.
I stopped working with Next a few years ago, so I can't comment very fairly on recent changes in the framework. However, it does appear as though it has become even more complex, and that was a significant art of what steered me away. The other part was simply a lack of cohesion with design decisions and direction. The middleware layer seemed like a poor design. Various opinions around things like default cache policies felt incorrect. I found myself battling their decisions too often, for too little benefit.
eknkc 10 hours ago [-]
I thought I hated React until I saw the samples on this page...
jfengel 9 hours ago [-]
Any time I see code in quotes I get the heebie jeebies. Code in quotes can't even be syntax checked until run time.
JSR_FDED 9 hours ago [-]
Philosophically Datastar is on the same page. Incredible performance and dramatic reduction in complexity.
bartwaardenburg 11 hours ago [-]
The fields/flags state model is a nice idea, having structured values separate from boolean state is something I haven't seen in other frameworks. How does this compare to Alpine.js or htmx in practice? They're in a similar space (no build, SSR-first) but I'm curious what made you go with a new framework rather than building on top of those?
dleeftink 11 hours ago [-]
Think Xstate[0] machines are a little more intuitive than the conditional value structuring displayed here in the example, but it is an interesting idea indeed.
Most of the time, it's enough to build in a simple, clean, and lightweight way.
Just like in the old days. Your server's resources will also thank you.
Furthermore, the simplicity of web pages is also rewarded by search engines.
If it were up to me, I'd build sites exclusively in .md format :)
speefers 11 hours ago [-]
[dead]
dmix 4 hours ago [-]
Rails does this perfectly with Turbo and Stimulus, Turbo does HTML-over-the-wire via SSR-first, server responds with small updates/appends of HTML as need etc, and then you lightly use stimulus JS controllers for the small stuff where HTML/forms don't make sense. https://hotwired.dev/
usrbinenv 60 minutes ago [-]
While it's definitely possible to build similar website with Turbo and Stimulus it would absolute NOT be the same thing and the mechanics of it would be radically different. I would argue using SSR at all times (and, consequently, workarounds like Hotwire, which make it look like it's not SSR) is the same kind of sin as using React for SPAs for personal blogs (i.e. things, SPAs don't belong to).
usrbinenv 4 minutes ago [-]
What you probably saw isn't code in quotes, but simply matchers like `price: "isPresent()"`. The () is there to signal it's a matcher, not a value. If this matcher doesn't exist, you'll get an error. The reason I chose () to signal it's a matcher is to distinguish it from values. Maybe there's a better way to do it.
wg0 8 hours ago [-]
Have tried multiple approaches. Sevelte. HTMX. Everything in between.
And came to conclusion that after certain complexity of UI - React kind of components are unavoidable if you want to be able to reason about your code.
Think of Shopify admin panel with product variations each variation having different pictures and what not.
Not saying not doable in plain JS.
But then Chrome can be written in NASM too, C++ is just...
iammrpayments 5 hours ago [-]
Shopify is quickly moving to Preact, and you can see that is paying off, I now see changes on the dashboard every week instead of every 6 months
lo_fye 8 hours ago [-]
I wonder how many users would prefer to have full page reloads (aka traditional server-side rendering) when navigating instead of all the insane http requests and ads we have today?
See also: HTMX and possibly even jQuery
bearjaws 9 hours ago [-]
Why use JS at all for SSR?
It's not a great language for it.
azangru 8 hours ago [-]
Where does the article say anything about js for ssr?
Bengalilol 9 hours ago [-]
I must have overlooked the site, but are there any working examples?
usrbinenv 31 minutes ago [-]
Yeah, several apps have been built with it, but they're not public (or not public yet).
Aldipower 9 hours ago [-]
Hate and love, the borderline framework for borderliners. SCNR
exabrial 7 hours ago [-]
What a breath of fresh air
kitsune1 5 hours ago [-]
[dead]
anthk 7 hours ago [-]
If the point it's to run propietary code, do yourselves a favor, ditch JS, and enable WASM for webapps and make most of the text web HTML5+CSS3 only. At least I won´t need to mangle User Agents to just read simple articles and images froma blog or a news site.
cies 7 hours ago [-]
I went with SSR for a new project started 2025Q4. I'm not against React, but when I have to make an SPA (or very interactive component in an SSR app) I much rather use Elm.
In order to do the JS that I have to do with an SSR app I went with Alpine.js. It reduces the JS I have to write and that fits my SSR approach.
It feels a bit like a modern jQuery to be honest: you cannot build whole apps with it, but just to sprinkle on top of an SSR it does really well.
joeyguerra 7 hours ago [-]
There are people who hate react?
austin-cheney 7 hours ago [-]
I strongly dislike React.
jmull 59 minutes ago [-]
Hate is too strong a word, but it’s junk.
ecshafer 6 hours ago [-]
I do, React is a scourge in UI development. 100x code and dev time for worse performance. Have you ever built a website in HTMX?
jollyllama 7 hours ago [-]
Yes but mostly because it uses NPM.
shimman 6 hours ago [-]
I've been working as a frontend dev for about 11 years. I've only ever used react for a majority of projects, also doing all kinds of work: porting angular projects into react, refactoring legacy react projects into modern react, building complex data visualizations for network topologies, and your basic CRUD stuff.
I dislike react because it's long overstayed its welcome. The vast majority of react projects are bloated messes and it truly feels like the react community is being steered by dev influencers that have very little experience working on projects (this includes the react maintainers themselves IMO).
There are way better libraries to write maintainable code in (svelte, solid, and even vue is better FFS). There are other mental frameworks that allow for good engineering practices as well like htmx or hotwire.
React is only here for the same reason that Java Spring is here, it was one of the early adopters that has too much momentum where leadership across companies are actively hostile to devs so there's no time to actually create good stuff but rather stamp out garbage so billionaires can be slightly more rich.
peytongreen_dev 4 hours ago [-]
[flagged]
kitsune1 5 hours ago [-]
[dead]
chattermate 10 hours ago [-]
[dead]
1GZ0 10 hours ago [-]
Yeah, no thanks..
I'll just stick with a $5 vps with lamp and jjquery
Then some bunch of geniuses decided it would be awesome to put everything together in the name of components. Today, you open facebook, the creators of React - normal drop-down with just a list of barely 5-6 items is a fucking component that makes 10 different requests. I would even argue this unnecessary forced interactivity is what perhaps annoyed users the most as everything always has to "load" with a spinner to the point of the platform being unusable.
Same goes for instagram. It's not just that, React is a hot ball of mess. It's not opinionated, so anyone can use anything to do anything. This means if you work with multiple teams, each one uses their own code organisation, state management library and general coding paradigm. Eventually the engineers leave and the new guy decides to do things his own way. I've honestly never seen a company with a great product run over React. Everything always is being re-written, migrated every 3 weeks or straight up is buggy or doesn't work.
React is the worst thing to happen to the Javascript ecosystem. The idea is good, but the execution is just piss poor. I mean look at Vue and Svelte, they managed to do it right.
To an extent this is how react works internally. There is a function which takes state and produces UI. In order not to have to re-render the whole UI if only a small part of the state changes, there is a diffing algorithm and "virtual dom" that is diffed against. Maybe it doesn't work exactly like that anymore but that's the gist of it.
This bottleneck could be alleviated if browsers shipped native dom morphing or even some kind of native vdom but we're stuck with userland js solutions.
I don't know about the other UIs, but on the web, some things impinge on the model you (and Redux) are proposing.
One thing is: you, in the gamedev world, have the luxury of having a frame buffer to write to. You fully control what gets rendered. Unfortunately, React and its cousins all have to deal with the idiosyncracies of the legacy browser environment. You have CSS, which applies and cascades styles to elements and their children in often non-obvious ways, and is a monster to deal with on any given day.
In addition to CSS, you have multiple potential sources of state. Every HTML slider, dropdown, input field, accordion, radio button, checkbox has its own browser-native state. You have to control for that.
On top of all of this, the browser application is usually just a frontend client that has to interact with a backend server, with asynchronous calls that require wait-state and failure-state management.
One thing that's in common with all of the above problems is: they're localized. All of these things I'm describing are specific to the rendering layer and therefore the component layer; they are not related to central state. A central state trying to capture all of these problems will fail, because component state has to be wrangled locally near where the HTML is; CSS also is component-level; and the network states are often very closely related to each component. If we maintain a central "game state", the data complexity just proliferates endlessly for each instance of the component.
So, the default these days is to keep state very close to each component, including network state, and often business logic also gets sucked into the mix. I try to avoid putting business logic in components, but people do it all the time unfortunately. But it does add to the complexity.
In other words, there is -real- complexity here, stemming from the fact that the web was never built to be a distribution+execution layer for rich applications, but evolved to become exactly that. It's not just bad application architecture or bad decisions by React maintainers.
Maybe I'm wrong, since I'm not a game developer and don't see what you're seeing on your side.
What I still don't understand is why the browser is that way in the first place, and why all of the native, not-browser GUI frameworks that people use are also that way. People opt into using React Native, even! But the regular run-of-the-mill frameworks that are widely used for native applications are also annoyingly complex to work with, so much so that I've repurposed my engine for when I want to create native applications and have been working on building a desktop UI framework within it that follows the same model I use for games (albeit nowhere near production-grade, just covering "the cases I need").
> the browser application is usually just a frontend client that has to interact with a backend server
I will note that this is a constraint that is shared with gamedev. Most multiplayer and even many singleplayer games these days are server-based.
Then computers got faster, much much faster. It became possible to redraw the whole UI from state every frame without it being a significant cost.
At the same time retained user interfaces managed to become more and more costly to do just about anything. I don't think for any particular reason other than computers were fast and they didn't need to do much better.
I find it really odd that there are user interfaces that take longer to rearrange their items than it takes for the same CPU to RayTrace a scene covering the same amount of screen area.
I can't really think of a statement that resonates with me less.
[1] I loathe this term, by the way. It's one of those terms that, I think, belong to a discipline of developers who love to obfuscate everything, even simple concepts, with unnecessarily opaque terminology until nobody can understand what the hell anyone is talking about anymore.
the problem is that the typical modern web page is considered as a combination of immediate-mode and retained-mode.
therefore, as it is wasteful to update all the page when only a few components on the page change, people want to only update parts of the page immediately when changes happen.
furthermore the typical modern web page only makes sense in the context of the modern web site, so some pages are almost everything on the page needs to update all the time, some pages are nothing here needs to update until the user does anything, some pages are nothing here needs to update at all, and other pages are just a couple components need to update all the time based on various things.
This context of what a web site is like is very much determined by the type of the site, where many e-commerce sites are affected by all sorts of data that occur outside of whatever page the user is on and need to update all sorts of different components on a page, many governmental sites are almost just static, with all sorts of variations in between.
Maybe <canvas> if you clear it on every frame.
>As I understand it, React was an attempt to shoehorn "immediate-mode UI"[1] on top of retained-mode UI
which I interpreted as the only possible meaning, in relation to React, being UI components that must rerender as close to immediately as possible vs. UI components that do not need immediate rerendering when the underlying data has changed.
I realize that is not a particularly correct use of the phrases, but then that is what happens when you use a concept from one type of development metaphorically in another type of development, memetic slippage as it were.
These are requirements the DOM / CSSOM addresses, you'd probably not have an easy time getting this right in a <canvas>.
"You don't know about X? Well, at least I know about X and Y..." Doesn't seemed like a good faith comment to me either?
And then you say "You misunderstood my intentions so I'm going to disengage". For what it's worth, I didn't interpret your argument as insulting someone, but also it wasn't a useful or productive comment either.
What did you hope to achieve with your comments? Was it simply to state how you know something the other person doesn't? What purpose do you think that serves here?
For my part, I also loathe the insensate writhing mass of frameworks, patterns and dependencies that is "modern" frontend development. Where you and I differ is I recognize a handful of extremely good ideas hidden in the morass. But I am perfectly happy dismissing the majority of it; if nothing else, you shouldn't come away thinking of me as a React fanboy.
Writing is a lossy medium for thought, and programming is no exception. I'd say at a minimum that you and I are on the side of programmers whose code is a medium for their own thought.
All of these choices really just comes down to cognitive bandwidth, context, domain, taste, any number of things, really. Which is what was behind my first (admittedly terse, slightly salty) comment.
What I condemn is someone who opts out of making choices for themselves in their software. Web dev just happens to have an unfortunately high concentration of this sort of thoughtlessness.
What you are describing is exactly what GP complained about: "state as something distinct from both the UI and the data source".
React can be 100% stateless, functional, and have the state live somewhere else. You just need to apply the same limitations as your model: components should be simple and not store data in themselves.
This is why people came up with things like Flux/Redux/Reducers/Immutability, to handle this in a standardized way, but nothing is necessary.
That is a ”controlled component” model which is bad for interactivity, especially text inputs.
If every keypress triggers a state change and rerender, the UI will be slow and things like focus management become complex issues.
Without a rerender, it must now use a reactive binding to update the field value.
If you don’t want to update state on every keypress, your component must be uncontrolled, store its state internally (in the DOM) and update it to a parent store e.g. when the user stops typing (debounced) or moves focus out of the field. These are not trivial things either, and as a result, components get more boilerplate to handle the UX complexity. And of course, there are now UX pitfalls.
Indeed, these are reasons why reactive patterns exist. Now, if they just managed to abstract away the tedium.
Also, focus management isn't really a thing in React, the vdom diffing means DOM nodes are updated instead of replaced so focus isn't lost or changed unexpectedly. There used to be a demo on the React homepage showing this, since the idea was very new to most people at the time - everything popular before it was just rendering template fragments to replace nodes and did have this problem.
"just" is doing a lot of heavy lifting here. Where do you store "pure" GUI state (button state, is expandable expanded, …)? Do you really want to setup Redux for this? (And no, the DOM is not an option in non-trivial cases.)
https://crank.js.org/blog/why-be-reactive/
Moving state out of HTML and into JS means we now have to walk this ridiculous tightrope walk trying to force state changes back into the DOM and our styles to keep everything in sync.
Given that problem, reactivity isn't the worst solution in my opinion. It tries to automate that syncing problem with tooling and convention, usually declaratively.
If I had to do it all again though, DOM would still be the source of truth and any custom components in JS would always be working with DOM directly. Custom elements are a great fit for that approach if you stick to using them for basic lifecycle hooks, events, and attribute getters/setters.
I recall the property passing model being a nasty abstraction breaker. HTML attributes are all strings, so if you wanted to pass objects or functions to children you had to do that via “props” instead of “attributes.”
I also recall the tag names of web components being a pain. Always need a dash, always need to be registered.
None of these problems broke it; they just made it irritating by comparison. There wasn’t really much upside either. No real performance gain or superior feature, and you got fewer features and a smaller ecosystem.
Even so, Lit is widely used to build very complex apps (Beaker, as you know, Photoshop, Reddit, Home Assistant, Microsoft App Store, SpaceX things, ...).
Property bindings are just as ergonomic as attributes with the .foo= syntax, and tag name declaration has rarely come up as a big friction point, especially with the declarative @customElement() decorator. The rest is indeed like a faster less proprietary React in many ways.
I also didn't often see Lit being used in a way that stuck to the idea that the DOM should be your state. That could very well be because most web devs are coming to it with a background in react or similar, but when I did see Lit used it often involved a heavy use of in-memory state tracked inside of components and never making it into the DOM.
That's an ok choice in some cases, but the web clearly moved on from that to be able to have richer interaction, and in a lot of cases, much easier development.
My usual go-to rule is that business logic belongs where the state lives - almost always on the back end for state of any real complexity.
With true web apps like Figma I consider those entirely different use cases. They're really building what amounts to a native app that leverage the web as a distribution platform, it has nothing to do with HTML at all really.
I've always maintained that no reactivity is a much simpler mental model. Mithril and Imba do this with better than good enough performance.
I think Remix 3 will be following this approach too.
The previous Remix was rebranded into React Router. Remix 3 will not use React and will apparently not use reactivity either.
https://remix.run/
There was a presentation last year:
https://www.youtube.com/watch?v=iZl0IKj0HHc
Model knows nothing about controller or views, so they're independently testable. Models and views are composed of a tree of entities (model) and components (views). Controller is the glue. Also, API calls are done by the controller.
So it is more of an Entity-Boundary-Control pattern.
Is there really a difference? Angular uses RxJS in a pub-sub scheme. (At least it did when I last used it.)
That of course led to developers building much more complex UIs. Which offset the gains from reactivity. Hence the mess and we're basically where we started.
Instead of HTML, think about GTK or Swing.
To add React-style "reactivity" to it, instead of just making a dialog to change the "title" of a document and committing the change when you press OK, you'd need a top-level "App" class that holds all the state, a class for state properties with IDs accessible at runtime which probably would be a variant (accepts any primitive type), a binding class to bind the toolkit's textbox to the App's state "title" property (because you'll probably want to bind a lot of textboxes, so it's easier to separate the code into classes), and then every time the user types something into the textbox, instead of using the toolkit's code that is already written for you which updates the textbox' state directly, you block the state change in an event handler, send the state change to the App class, let the App class figure out the differences between the current state and the new state, and then it calls some callback in the binding class that is responsible for actually changing the text in the textbox to reflect the new App state. You'll probably run into a ton of issues (selections resetting, assistive technologies bugging, etc.) that you'll have to deal with externally somehow. All just to make it do exactly the same thing it would have done anyway.
It's like you have a fully autonomous robot and you want to add marionette strings to make it move.
And then said developer does what they think feels right: "I have my state and I simply want all the fields to reflect my state". So they try and rewrite the component into some sort of mini immediate-mode style component. All of the event handlers get wired up a single "layoutComponent" method that tries to call all the UI component setters based on the current state with all the problems you alluded to. I know I've done this type of things numerous times before going back all the way to my first internship, well before React was even a thing.
I think modern frameworks solve the reactivity issue this well enough, that it really doesn't matter if the underlying framework is not natively reactive. I will say though that I've primarily used Vue.js where most state is relatively local and we don't try to re-render the world on every input. I think part of the problem with modern dev is likely that React has become the default instead of a simpler framework like Vue.
Ironically, in most cases events are only used by one object, but you always want to consider the possibility that two objects will want to observe the same event, so now you need an entire event dispatching class, and then you'll want observable properties, and the nail on the coffin is going to be observable lists. When you reach that point, one event triggers another, which changes a property, triggering another event, and so on and so on. You are 5 layers deep into event callbacks. The call tree just has the same "callCallbacks()" method over and over again.
Bugs start happening because of the order in which callbacks are called becomes important, so now you need a way to give some callbacks priority over others, or make them happen after all normal callbacks were called. One callback destroys an object which has callback on the event that destroyed it, so you're going to need a wrapper around your callbacks that gets notified when callback's object is destroyed to change its reference to null in order to avoid executing code on the destroyed object if this happens while iterating the callbacks in the event dispatcher. Sometimes calling callbacks in wrong order is a performance hit, when it doesn't just get stuck into an infinite loop and you run out of stack.
I wonder if there is GUI programming paradigm that solves all of this or that you can call the "best" one. Maybe it's reactivity, maybe not. Who knows.
But yes, React is a mess. JSX was the original sin of mixing HTML inside JS. And those bundlers and tree-shaking at build time? Ugh.
What if you had this instead: https://community.qbix.com/t/loading-at-runtime-the-web-fram...
https://leanrada.com/htmz/
Oh my. If it works just like Ajax from >10-15 years ago, then I will be super happy. :D
Maybe focus on a use-case? Something like, "No-build, no-NPM, SSR-first JavaScript framework specializing in Time-to-interactive" - maybe?
React is not popular simply because engineers hate themselves or enjoy pain. There are problems it solves, and problems it creates. Explain what problems your solution solves, and feel free to dunk on React while you're at it, but write a tagline like this and I'm not gonna take you seriously.
Anyway, interesting approach for up to medium pages (not apps!). Totally not replacement for react.
There's nothing wrong with either of these if used correctly. Thus "hate" is a rather shallow argument.
The SSR-first angle is especially interesting. Most frameworks bolt on SSR as an afterthought. Starting from HTML and progressively enhancing is how the web was designed to work, and it is telling that we keep circling back to it.
I've also go a much simpler Next.js app with a build time of 45s.
I do love the idea of a batteries included framework for the JS ecosystem, like the mythical Rails for node, but as long as we're gluing random stuff together... This is a really nice combo. I also love using Hono and React/Vite with TRPC.
I stopped working with Next a few years ago, so I can't comment very fairly on recent changes in the framework. However, it does appear as though it has become even more complex, and that was a significant art of what steered me away. The other part was simply a lack of cohesion with design decisions and direction. The middleware layer seemed like a poor design. Various opinions around things like default cache policies felt incorrect. I found myself battling their decisions too often, for too little benefit.
[0]: https://github.com/statelyai/xstate?tab=readme-ov-file#super...
Most of the time, it's enough to build in a simple, clean, and lightweight way. Just like in the old days. Your server's resources will also thank you. Furthermore, the simplicity of web pages is also rewarded by search engines.
If it were up to me, I'd build sites exclusively in .md format :)
And came to conclusion that after certain complexity of UI - React kind of components are unavoidable if you want to be able to reason about your code.
Think of Shopify admin panel with product variations each variation having different pictures and what not.
Not saying not doable in plain JS.
But then Chrome can be written in NASM too, C++ is just...
See also: HTMX and possibly even jQuery
It's not a great language for it.
In order to do the JS that I have to do with an SSR app I went with Alpine.js. It reduces the JS I have to write and that fits my SSR approach.
It feels a bit like a modern jQuery to be honest: you cannot build whole apps with it, but just to sprinkle on top of an SSR it does really well.
I dislike react because it's long overstayed its welcome. The vast majority of react projects are bloated messes and it truly feels like the react community is being steered by dev influencers that have very little experience working on projects (this includes the react maintainers themselves IMO).
There are way better libraries to write maintainable code in (svelte, solid, and even vue is better FFS). There are other mental frameworks that allow for good engineering practices as well like htmx or hotwire.
React is only here for the same reason that Java Spring is here, it was one of the early adopters that has too much momentum where leadership across companies are actively hostile to devs so there's no time to actually create good stuff but rather stamp out garbage so billionaires can be slightly more rich.
I'll just stick with a $5 vps with lamp and jjquery