> It's funny when you look at the code and think... huh, that's actually a lot easier than importing a huge library with way too many props
I had this realization after the 3rd or 4th RiotJS major version update. It started getting harder to do it the opinionated way. I realized that every minimalistic JS framework would eventually suffer this fate as totally innocent feature requests gradually accumulate into a monstrous pile of hooks, events and other side-effect bandaids.
I don't even use jQuery anymore. I will use things like ES modules to help organize code, but you don't need to run a goddamn npm command to use any of that technology. All of this is a global browser standard, not something you have to vendor in.
I look at MDN as the Bible these days. If you take a leap of faith, it will carry you almost 100% of the way. The frameworks will cripple you after a certain point. I can't say this would have been true ~5 years ago. Things have shifted rapidly with browser APIs converging on a powerful set of primitives (modules, flexbox, grid, etc) that are now very consistent across platforms.
I like the fact that you said “I can’t say this would have been true ~5 years ago”.
React et al. exist because there weren’t global standards around these things and composability suffered. Now that we are all playing the same chorus, these frameworks provide little more than component libraries to reuse. This can be done with ES modules. JSX is why most React folks stick with React, not knowing they can use Preact or just NakedJSX if they wish.
I just wanted to verbally concur that vanilla JS is more than capable of doing everything you need. Custom tags. Shadow dom. Composed UI. etc. if you are ok with returning HTMLElement vs a JSX closure.
> JSX is why most React folks stick with React, not knowing they can use Preact or just NakedJSX if they wish.
The large ecosystem of component libraries and the backing of a large corporate company is why people continue to use React. That, and that the extra 100kb that comes with React is generally dwarfed by the actual application in any large app.
I'm using preact for a few projects and the integration with React stuff is generally seamless, but there are enough rough edges encountered that looking back I wouldn't mind taking the difference of a few dozen kB to avoid them all. The vast majority of my load time is taken by TTFB, even from the Cloudflare Pages local cache, so worrying about kilobytes seems misguided.
No, React exists because there was a need for a template engine that’s easy to use.
There is still no global standard for templates.
Just like mustache, Twig, Java Server Pages, Jinja, ERB… every language has this problem. You have a bunch of components written in HTML and you need to mix and match them together in a bigger unit. React+JSX let you do that easier than appending DOM components. Before React, you’d use different libraries that did what React did.
The ONLY major language I can think of that has templating baked in is PHP.
HTML has built-in templates now, and custom elements (web components) provide composability. If the built-in templating is not quite powerful enough (it has no logic or variables) there’s developit/htm which is basically JSX but parsing in the browser.
React is still easier, but it comes at a maintainability tax because you have to keep upgrading to new react versions and port to new react wrapper framework versions if you want to keep a codebase in active development. Vanilla web development has no such problem because web standards remain backwards compatible.
For a small project where I don’t care about SEO / server-side rendering I absolutely prefer vanilla web dev over React now.
> React is still easier, but it comes at a maintainability tax because you have to keep upgrading to new react versions and port to new react wrapper framework versions if you want to keep a codebase in active development.
There has been one breaking version of React (the recent React 18) in it's 8 years of history. Upgrading React versions is a non-issue.
Wrapper frameworks like next.js can come with a much higher maintenance cost, but you don't need to use those to use React (and I think most people don't).
Yes, it does! But while I have not used them yet, the approach used by them (via SGML tags) is not new and many libraries / XLST have done it before in the past 20+ years and I find the approach usable at best. It's too verbose for my taste and it never really caught on, and I find it hard to think that it would catch on this time.
And this is absolutely true in CSS now as well. I find a lot of people are needing to rediscover the standards now that they've upped their featuresets.
React exists because Facebook needed to sync DOM elements in different parts of webpage with a single source of state. There is still no global standard that solves this problem.
You mean state handlers? Those are one of the main reasons people adopted OOP at the 80's.
The observer pattern got pretty much standardized by the GoP book, but people overwhelmingly prefer to run some non-standard specialized thing, as it's usually much simpler. It's a pretty much solved problem since way before a lot of current developers were even born.
All of (ok, a lot of) the React's complexity comes from it being a generic library that must support every kind of usage. Any standard would have to be as complex.
Web components solve encapsulation of structure, style, and behaviour within a single component, but they don't solve the larger state problems, because web components don't come with any sort of state management beyond what you can do with normal Javascript.
React does provide components, but there's not so much different in React components than any other component system. The main reason to use React is the state management it provides on top of those components, making sure that state is in sync across the whole application.
In my experience, the hard part of larger applications is that handling of application state. Rendering data can be done in umpteen different ways, and they're all pretty much good enough, but handling application state in such a way that every component remains in sync with all other components is hard.
Yeah I think some people glorify "simple", low level solutions, which work fine for sprinkles of interactivity. But if I'm building a non trivial UI application - give me a framework please!
Not at all. Without React (or a similar framework) you are still left with the options of:
- Manually keep track of UI state (which is complex, and often leads to hard to maintain spaghetti code)
- Recreate an entire DOM tree every time you re-render (which is slow to the extent that it will often lead to performance problems in practice). Apparently this is not as slow as it used to (so you could probably get away with this sometimes - and you could before), but it's still generally a better idea to use a framework as you get better performance for very low cost.
There are plenty of non-React frameworks that will you these benefits too. And many of them are much smaller. I think the reason to use React specifically is more "business reasons" such assurances that the framework will continue to be maintained, library ecosystem, developer pool, etc. Other frameworks are often technically superior, the difference just isn't that great.
React et al use a virtual DOM, not shadow DOM (unless you specifically render it to shadow DOM).
They are a better* way to manipulate DOM in that you no longer need to manipulate the DOM, you just build a function that returns what the DOM should look like and it figures out what transforms need to happen.
*They’re pitched as a better way, and I think it’s better, but people can reasonably disagree
Templates and shadow DOM help a lot with creating and cloning of large subtrees, but time to first render and caution around page re-layout still require attention to do well at scale.
It depends on the type of relations between the updates you want to make, for example adding/removing a class can group DOM elements. Updating all elements with this class is easy.
the ability to do efficient updates in large DOM.trees
It was the ability to do efficient updates based on large VDOM diffs. The speed of updates is the same between a React VDOM-diff update plan and a direct update of the same size based on e.g. observers.
Yes, that's the point: computing what needs to change using observers quickly becomes hard. React allows you to run all updates against an unchanged view; observers can interact with each other's updates.
While React proper may be too large, I find the approach indispensable for more complex interfaces. One can pick Preact instead.
But it's indeed overkill for adding small bits of interactivity to large, mostly static documents.
They only do that if you build a dependency graph instead of a dependency tree and iff the observing framework allows that, and without any loop resolution method. The common technique for graphs under dumb observing is to create a single update routine and pass the name of an emitter to it. I’ve built literally hundreds of interfaces using this (most of them what they’d call “more complex”) and never met any issues React kids are taught to be scared of. UI dataflow was never even a serious concern to be worth a name.
The whole premise of React compares it to a “generic detergent” which doesn’t really exist.
I agree that a tree would solve the problem. How do you efficiently compute such a tree, given an event like clicking a button, somewhere far from its potential root?
I'm not an expert in frontend development, but all solutions I've seen either used a variant of virtual DOM, or two-way bindings (the latter a non-starter for me). What did I miss?
You don't have to compute it, it is natural. Observers subscribe (this builds a tree), receive notifications and propagate changes via a set of [possibly common] routines that update other values.
The difference is, React dataflow is "returns new state with old state and (returns new state with old state and (returns new state, which triggers the above internally), which triggers the above internally), which triggers the reconciliation".
And the classic way is "triggers a state, which triggers a set of states, which triggers a set of states, and every triggered control flags a redraw internally with a proper granularity at gui side".
or two-way bindings (the latter a non-starter for me). What did I miss?
That they may be a starter, I guess. Or you can use "control X observes data A", "data B, C observe control X" dataflow. It doesn't really matter, because two-way bindings simply push input down to the data level instead of treating controls as explicit data storage. With two-way bindings you can erase the UI layer completely and still get a fully functioning object, which is useful for automation and for reusing/macroing of a proper functionality.
No, jQuery existed for that reason. React has other reasons, one of them being that manual DOM tracking and manipulation is brittle and annoying and the way React works turns that around completely.
I'm not sure what Preact or NakedJSX offers me that would make it a better choice than React.
NakedJSX is primarily a low friction static site generator, it is not intended as a React or Preact replacement. Except for cases where something like React is overkill.
I had this realization after the 3rd or 4th RiotJS major version update. It started getting harder to do it the opinionated way. I realized that every minimalistic JS framework would eventually suffer this fate as totally innocent feature requests gradually accumulate into a monstrous pile of hooks, events and other side-effect bandaids.
I don't even use jQuery anymore. I will use things like ES modules to help organize code, but you don't need to run a goddamn npm command to use any of that technology. All of this is a global browser standard, not something you have to vendor in.
I look at MDN as the Bible these days. If you take a leap of faith, it will carry you almost 100% of the way. The frameworks will cripple you after a certain point. I can't say this would have been true ~5 years ago. Things have shifted rapidly with browser APIs converging on a powerful set of primitives (modules, flexbox, grid, etc) that are now very consistent across platforms.