Weren't jetpack compose and swift UI inspired by React? I saw it somewhere in the android docs and now its probably deleted, I can't find it anymore.
But then again, I don't have "decade" of experience in tech, yet. I have no idea if building huge web apps (i.e airbnb) using jquery or plain js with large teams is as enjoyable back then? My thought process is changed, I can't even think on how to solve the state management, dom manipulation, side effects etc with plain js anymore.
Nowadays I just built on what I'm familiar with and focus on what I want to build. who knows, maybe in the future I will also complaint about new frameworks and mention how good React was :)
I've interacted with a not insignificant number of people who seem to hold this opinion. Usually their arguments boil down to one of:
* Frontend engineering is always chasing the next shiny thing, and react is one of them. There's probably some truth to this historically, but react has been a thing since 2013, and pretty 'mainstream' since 2015 or so.
* Frameworks and libraries add 'complexity'. I almost never hear anything specific when I ask about what complexity they're referring to. IMO if you work on a non trivial application without a framework, you'll just end up inventing your own poorly maintained, poorly tested and poorly documented framework. This might be fine for a weekend project, but rarely something you should do at a company.
* People also often complain about the compilation/bundling step. This might've been harder to manage historically, but now with battle tested frameworks like expo, nextjs, meteor etc, there are very few reasons to write a webpack configuration or build pipeline by hand.
Coming from a Rails background, it's pretty jarring. It's like the difference between being told, "Here's how you build a house" and "Here's how you use the tools in this toolkit".
React offers more freedom at the expense of guidance, and you get much less standardization as a result.
I get why some wouldn't like this but for me it's a breath of fresh air and why I continue to love working with it.
That couldn't be further from the truth! While I appreciated having a path laid out for me when I stated out, 10 years end I much prefer forging a path myself.
Mastering these tools, and leveraging my own creativity in how I use them, is much more enjoyable.
I think the root cause of this is react not really being a framework, rather just a library that allows you to write declarative code involving state that in the end, outputs a DOM tree. IMO it does that quite well.
It doesn't have very many opinions on how you should structure your code, how you should organize your state, how your routing logic should work etc. I think that's where frameworks come in. React was quite popular long before frameworks like nextjs, meteor, remix, ... became 'mainstream', causing lots of developers to invent their own (poorly maintained) frameworks.
In defence of the haters, I think we’ve all seen our share of horrendously organized React SPAs. Dependency hell, (seemingly) infinite prop drilling, components thousands of lines long, the list goes on.
Some people think they hate React, when in reality they hate a specific implementation of it.
I was shocked at how much time some teams spent on reinventing wheels rather than using some off the shelf components. "We need everything to be done in house so we can document it and have full control". But... designing all your own widgets is going to take months. "React makes it easy though, so don't worry - we know what we're doing' Yet... they didn't - untestable components that couldn't support what the original requirements called for months earlier, etc.
You know how people crap on PHP because there's so much 'bad' PHP out there? But others say "it's just how you use it - frameworks XYZ are great!". I feel the same way about React. There's probably some great examples out there, but I somehow tend to see a lot of lesser quality stuff.
Most of the use cases I've seen up close... there wasn't any real magic or benefit to React vs something else, but everyone was jacked to get more React experience on their resume for their next gig. It didn't really matter if the resulting output was good or not, just that they used React.
I don't hate React - it's a library. I'm tired of much of the B-team players requiring it to be considered "professional" (while simultaneously) eschewing testing and documentation).
For people who have chosen it, and get to stay on the same project for several years, honing their skills on one codebase and iteratively improving, great. Enjoy.
In my previous startup the frontend developers decided to develop their own design library from scratch. My suggestion was to start with an established library and just adjust the style to match our look, but they wanted full control and ownership of the code. 3 years later, most of them left for new jobs and the library only contains a very basic set of components. Apparently accessibility and the rest of the "remaining 80%" part of the "80% completed" components were more difficult than they assumed. At least they had fun and could pad their resumes when they applied for new jobs, leaving others to maintain their m
This mindset was so different from the backend teams in the same startup. They preferred stable and known frameworks and libraries, and focused on the business logic. I had a feeling that the backend teams just got stuff down with little drama, while the frontend team was engaged in endless debates and rewrites. They had their own issues of course, but once they had fought the battle of choosing which language and stack to use, they stuck with it.
I worked with both and tried to stay away from most of the discussions, but it is clear to me that autonomy only works when you have a good balance of senior and junior developers that can have a discussion with the others without needing to "win" every time. As a senior developer myself, I have often learned new approaches from junior developers who have found a problem and dug in deep. Unfortunately I have seen too many senior developers and junior developers not listening to good advice from each other. The juniors think the seniors are outdated, while the seniors think the juniors are not capable.
Like most problems in IT in general :-)
I wonder what are the frameworks or libraries that have exactly one widely accepted, idiomatic and correct way of doing most things, where the technology itself discourages anything else? Angular, maybe, at least with how batteries included it is?
The hoops I have to jump through to get the back button working.
Same for people that have never used Angular, or only used the old AngularJS 1.x
I have more experience with Angular, but I don't hate any of the other frameworks, I've built apps with React, Svelte and tried out Vue.
Drawing canvas: https://www.tldraw.com/
Code playground: https://replit.com/
Supabase dashboard: https://supabase.com/
Vercel dashboard: https://vercel.com/
Workout tracking: https://workout.lol/
Chatbot: https://chatgpt.com
Note-taking: https://www.usememos.com/
Tax filing: https://ustaxes.org/start
Python notebook: https://marimo.io/
LoL info: https://www.op.gg/
Sports matches: https://www.sofascore.com/
Trading news: https://seekingalpha.com/
Website builder: https://mmm.page/
Podcast maker: https://podcastle.ai/
The issue (and this isn’t React’s fault) is that every single web app is so obsessed with measuring analytics and engagement metrics and loading multiple ad containers and and and…
Whether Vite, or Svelte, or Vanilla JS, when you start stuffing a site with all these tracking pixels and other junk, they are all horrible.
There is likely a bit of observer bias going on with your comment, as many popular sites these days run React and they happen to run like crap due to the reasons I listed above.
They're definitely horrible from a moral standpoint, but if you look at the flamechart of JS activity in your browser you can easily see that they sit idle 99% of the time and only send events to an API as low priority background work when the browser does things. They aren't what makes websites slow.
That probably explains why the Amazon website just took 5 seconds to load on my phone while on a gigabit connection at home.
it very much depends on the type of app you are building, but I think many web applications could at least start with htmx and then, when more complex user interactions present themselves, use an island of interactivity approach that localizes the complexity.
this keeps overall system complexity as low as possible for as long as possible, and you may never need to go beyond htmx, which can lead to a much less complicated codebase [3]
[1] - https://htmx.org/essays/when-to-use-hypermedia/
[2] - https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it
[3] - https://htmx.org/essays/a-real-world-react-to-htmx-port/
1. HTMX itself
2. Your backend language Go/Java/whatever
3. Whatever JS framework for your interactivity islands
But yes we are all on the same team here of reducing complexity in the codebase and if HTMX works for you go for it.
My assumption would be that if you haven't seen anything, even from the creator, then you just have different expectations to the people who do get value from React
refine: https://github.com/refinedev/refine appsmith: https://github.com/appsmithorg/appsmith
there are heaps what are you talking about!
The trend to shove web frameworks into everything has ushered in a nightmarish decade of slow, dysfunctional websites, that - despite being over-engineered to high heaven - hardly deliver an improved user experience compared to what we had in 2008.
There's a class of frontend dev for whom - no matter the question - the answer is always some unholy combination of React / Node / Vite / Angular / Vue / Nuxt / Next / Bun / Deno / Svelte / SvelteKit / etc - preferably running across two dozen Docker swarms, ruled by the Red Queen (kubernetes). "Oh, you want to put your CV online? Sure, let's spend the next three weeks plotting out the state flow diagram for your 'app'... "
The reason React is particularly disparaged, imho, is because the framework fashionistas have moved on to chase the new shiny thing, and everyone else has always hated all these frameworks to begin with, so there's no one left to defend this particular hot mess. The same fate awaits the rest of the frameworks, in time.
Compare it with the nightmare of JQuery, where any line of code can affect any UI for whatever reason.
> Compare it with the nightmare of JQuery, where any line of code can affect any UI for whatever reason.
False dichotomy, and a somewhat strange one, given jQuery and React aren't even remotely aimed at solving the same problem?
You're free to stick to a functional paradigm in JS without requiring the overhead of React (and all the cruft that tends to pile up around React - build systems, compile times, masses of dependencies, the inevitable CVEs for those dependencies, etc.)
But more importantly, I'd respectfully note that you're pre-supposing that UI state rightly lives in JavaScript, which is a point of view already limited by framework-centric assumptions.
If it's unnecessary to use React et al, why is it necessary to complicate your application server with UI concerns so that it can build a big html UI string that is sent over the wire? And this only works for web browsers and no other clients?
Instead, it could be a simple API server that doesn't need to know about the UI at all.
There are obviously trade-offs in either direction, but to talk about necessary vs unnecessary doesn't seem to reflect that. There is nothing more necessary about one set of them over the other.
A 'simple API server' sounds lovely, but it's not getting your website to anybody without a frontend - and the complexity of the frontend offsets any savings made by simplifying the backend. I'd also very respectfully push back on this 'simple API server' business - serving /fie/fo/fum.json really isn't very much simpler than serving /fie/fo/fum.html; you have identical business logic, plus you've now got messy bi-directional JSON objects and hundreds of Ajax calls over unreliable end-user connections to contend with. It's the voluntary introduction of hundreds of unnecessary failure points. For most 'simple API servers' there's an alternative, and much simpler, much safer, much saner HTML server.
For that tiny number of websites that do require accompanying apps (mobile, etc), 97% of these could be solved with a thinly wrapped web-view. Those that cannot generally have special needs, and therefore cannot be solved by simply serving the same API endpoints across web and app anyway. If you're already separating your web and app APIs, plus now you've got a tangled web frontend to contend with, I'm really not seeing the benefits of reorienting your backend around APIs to begin with. A backend serving HTML to web, and a custom API to mobile is much more elegant and flexible (and doesn't actually require a soup of Javascript anywhere).
But we're already in the 3% of the 3% here - truly unusual applications. The vast, vast, vast majority of use cases were already solved by a server serving HTML.
Both are used for rich UI experiences.
So is Microsoft Frontpage, or Figma, or wgpu over wasm, or my friend John, the UI designer. Are these all directly comparable tools? Does John lose marks for not being downloadable over npm? (I can get him to compile TypeScript, but I can't seem to get him to compile into TypeScript)
You're describing websites simple enough that they're often used in beginner tutorials for web development.
Online shopping and text-based social networking absolutely and emphatically do not require a spaghetti soup of JavaScript frameworks. These were relatively simple websites to build for decades before web frameworks ever came along.
There's a huge difference between making a simple prototype of a concept and making an actual production app that fulfills a myriad of requirements that help you run a successful business.
No one has ever sat in front of a shopping site and thought - 'you know what this needs? A dozen extra mb of JavaScript that introduce no actual new customer-facing features, but that put a noticeable delay in every interaction, break the user's scrollbars and screen readers, and dramatically complicate maintenance.'
What a beautiful Straw man. What are these social media sites with more than one framework?
> ever sat in front of a shopping site and thought
But do you know what actually think? That they want to have products filtering, they want to have more products loaded with a simple button click, they want to add reviews and comments, they want to see product photos (or maybe even 3D models) - all fast without unnecessary page reloads. It's your problem you can't build it without breaking user experience.
In general, if a prospective employee told me they needed React to implement website comments, I would not walk away with a very high opinion of that dev's abilities.
> But without framework you in the end just create a custom one
Only if you've only ever written React-style webpages, and can't imagine any other way a website may work. Which, needless to say, would reflect a very limited experience of the web.
* Or just a plain XMLHttpRequest call? Dynamic loading is exceedingly simple, and certainly doesn't require a convoluted web framework.
> full page reload aversion that users supposedly have (they don't, they have much more of an aversion to endless spinners and websites that break their browser's scrollbars and back buttons)
I'm simply saying user wants performant websites. You're basically saying the same. Full-page reloads are, ceteris paribus, always slower than some JSON payload. And when you're saying to use HTMX, I then don't understand what you mean by "minimal to no JS".
> Only if you've only ever written React-style webpages
Again, I'm not saying anything about using React specifically.
> convoluted web framework
Yet another straw man.
I wrote an essay about this here:
https://htmx.org/essays/splitting-your-apis/
Also, producing JSON often involves reflection and can be more CPU intensive than straight templating (w/ fixed properly lookups) depending on your technology. Finally, the size delta between JSON and hypermedia is lower than most people think, particularly with compression:
https://github.com/1cg/html-json-size-comparison
in most real world systems i expect data store access to be the dominant latency issue
some people have had good success w/htmx from a performance perspective (2x+ speed, 1/2 memory consumption):
https://htmx.org/essays/a-real-world-react-to-htmx-port/
but of course it depends on your use case.
I think htmx would be excellent for an e-commerce site, which is mostly text and images and relatively simple, coarse-grained user interactions.
the speaker is referring to them not needing to write javascript for a specific feature, which is true, but they do use scripting for some aspects of the application, which is perfectly acceptable in hypermedia-driven applications:
https://htmx.org/essays/hypermedia-friendly-scripting/
regardless, the wins are obvious
"Minimal", maybe, "small to no", nay :D
Considering the original phrase was 'minimal or no', I am glad that you now agree.
> you linked the presenter literally says - "no JavaScript, just HTMX" - but HTMX is written in guess what? Very dishonest.
It's difficult to take this seriously. Just wait until you find out most of Python is written in C! Very dishonest!
> It's difficult to take this seriously. Just wait until you find out most of Python is written in C! Very dishonest!
Now I understand, you're just obtuse.
This seems like an exceedingly mean-spirited and unconstructive type of response to have to people who have been giving up their time trying to explain a different point of view to you. I would also gently point out the HN guidelines at this point.
I note you haven't responded to my more substantive reply here,[0] so I am unsure you saw it. I would encourage you to read it with less of a zero-sum 'I-win-you-lose' mentality. I won't be engaging with you further though.
That must explain why websites are so fast and responsive these days! /s
If you're wedded to the idea of dynamic reloads, which - imho - you ought not be, HTMX or Turbo are ways of achieving that without needing to write any JS. HTMX is designed to complete HTML as a hypermedia language, which it does using JS, but it itself does not require any additional JS to use. I'm sure the authors would dearly love it if HTMX's ideas were taken directly into HTML5, and they could scrap the JS library altogether. Its use of JS is an implementation detail borne of necessity.
If you're coming from SPAs and can't imagine websites working any other way, I highly recommend reading something like Hypermedia Systems (https://hypermedia.systems/). Come with an open mind, let it be your gateway drug. HTMX builds on a very old tradition of hypermedia, all the way back to Computer Lib/Dream Machines, through systems like HyperCard, to the actual, original definition of RESTfulness (that modern Ajax SPAs generally do not meet). It draws deep from the hacker ethos (you know, that thing that this website is about!).
Personally, I don't even think HTMX is all that necessary. What I feel like you're missing is that the overwhelming majority of websites are technically very simple, and their value to their users is in their contents, not in their stack. Did you notice the full page reload when you hit Reply on your comment, here on HN? Were you terribly put out by it? Would HN be an improved website were it full of spinners and Ajax? I would respectfully suggest it would not. It delivers amazing value running as a Lisp program on a machine under someone's desk.
It's not, it's precise.
Sorry you wasted time writing all this, because I don't care about hypermedia systems - it's not that it's bad technology, I simply don't want to write yet another awful templating language. But that's just an aside, because once again you're talking about something else. But okay, let's switch to debating HTMX. My point then still stands: you simply need JavaScript. Now instead of this useless arguing, go find/build some big e-commerce website with this hypermedia stuff (or truly with no JavaScript) and then we'll see.
they are pretty big
"Our framework is so slow that we can't possibly manipulate data in a reasonable time frame, so we'll just lie to the user and say we did! What could possibly go wrong?"
Also in the running: giving absolutely no indication whatsoever to the user that anything succeeded or failed or is in progress at all (aka the Apple approach).
Incurred a bill of $800, and reached out to me. Gobsmacked!!
I think you're projecting here. Its fine not to like trends in tech, but tech will change whether you like it or not. The people who jump on every new thing and stress about having to learn it all will keep doing it. That doesn't mean that anyone else hated it all to begin with. That's a pretty weird assumption to make. Even this thread is full of people who enjoy using React. Meanwhile, React is pretty stable and boring if you ask me. Your nightmarish decade will be extended. I'll light a candle for you.
It's the apps with unique requirements that need to be coded, not some pages that present some info in some way that's slightly different, stylistically, and not standard at all.
- How things actually work are very hidden and unintuitive
- Very easy to make mistakes, easy to write low performance UI
- High cognitive load, constantly thinking about how many times things run, what's in dependency arrays, what should go in useCallbacks and useEffect etc
- Overused, part of community sometimes encourage people to use React and some dependencies that's unnecessary for the project, only adding overhead and complexity
- Easy to mix business logic with UI logic
I work with mobx at work which just does a better job of letting us focus on business logic. Components observe computed models directly, no prop drilling, no context. The `createTransformer` map function is the key to mapping dynamic collections to computed models, handles GC in cases where you want to go from computed model to another computed model so you don't manage a bunch of WeakMaps yourself.
The React maintainers and community buy into complexity too readily. Probably why SolidJS (which unlike mobx also provides the view layer) is gaining traction.
What's surprising to me is that React 19 seems to be doubling down on hooks, adding more cognitive load by increasing the number of hooks you need to be aware of and their particular behaviors and requirements. Doing that instead of moving toward the more universal reactivity model that MobX, SolidJS and even frameworks like Svelte 5 are starting to adopt.
https://overreacted.io/making-setinterval-declarative-with-r...
I agree with this. Luckily there's some work being done on this - check out the new React Compiler[1]
> what's in dependency arrays, what should go in useCallbacks and useEffect
This lint plugin[2] from the react team helps quite a bit with this
[1] https://react.dev/learn/react-compiler [2] https://github.com/facebook/react/tree/main/packages/eslint-...
A lot of us complained, very vocally, about how bad MongoDB was.
So yeah nothing wrong with the concept of react, just the usual and terrible javascript ecosystem churn with stuff we don't need, but now everyone will have to update and so do we. Nice if you have a dedicated frontend team for every of your apps, not so nice for a small team that has to manage many apps across many clients.
I like major (potentially) compatibility breaking updates every 10 years or so, not every 3 weeks.
So yeah, we went off react to vanilla js, htmx and liveview type stuff which makes this all far simpler. Dev is also far simpler for us; all the pitfalls are no longer there. There might be some advantages to react in some cases; we won't look back; we never had a more relaxed team especially since we ditched nextjs and react; the trying out of other tech for frontend made us realize react was wrong for us all along anyway. ymmv of course.
I don't think that there are many good options for front end that are maximally stable out there:
https://endoflife.date/angular
Unless you want to look at something way more niche, you probably won't find something that has a main version supported for 5-10 years without major changes. Then again, that's usually not even the case with back end frameworks either, the closest you can get is either language runtimes like JDK (2014-2030, albeit the open source versions seem to end support in 2026), or maybe OSes like RHEL (e.g. 8 has a support timeframe of 2019-2029 or the extended option is until 2032).
In short, there is churn everywhere and I don't think you can simply pick any stack that is used for web development and will get exposed to the world (and therefore needs security patches), that will still work okay with no breaking changes along the way in 5-10 years or so. The only difference is how bad the individual choices will be.
as for why I personally choose React was due to the job market, community support, debugging exp, TS support, and JSX just felt much more natural to me. I don't go everywhere hating other frameworks though. I think its good that we're tackling the same problem with different solutions, we have more choices.
>as for why I personally choose React was due to the job market
From my experience, this is the problem, and I don't know that anyone is to blame for it. React's success has created skill drift away from the web platform. When I first started as a web team manager, my new hires knew the fundamentals of web standards: html, css, js, and some libraries to make those easier to work with.
Now, most entry level web devs know some flavor of React, full stop. These aren't Bay area web engineers, these are the web mechanics that need to get into whatever is thrown at them and keep it working, or make it start working again. I know losing grip of the platform is short-sighted in principle, and for the purposes of my team is immediately impractical.
Choosing react is not necessarily drifting away from the web platform. I choose it as my main stack when starting new projects.
Also react uses (or promotes) web-hostile anti-features like document level event handling and virtual scrolling, which are PITA from a devtools tinkerer perspective.
useActionState: is a new hook to order Actions inside of a Transition with access to the state of the action, and the pending state. It accepts a reducer that can call Actions, and the initial state used for first render. It also accepts an optional string that is used if the action is passed to a form action prop to support progressive enhancement in forms.
Delusional gobbledygook.
Could you elaborate on this? I'm not sure what an "async meta higher effect" is.
Reading in between the lines though, I suspect you're talking about state management. You might benefit from one of many state management solutions out there - redux, mobx, legend-state etc. Keeping and passing around local state spread out across lots of components can get unwieldy pretty quickly.
benefit from ... Redux
>_< had a good laugh, thanks! I imagine writing a hierarchical reducer every time I have to update x in {a:{b:[...,x,...],c:{{{...}}}}}-like structure. Mobx is close, but in the same "unengineering of overengineering" category.
(Edit: I don't think that parent comment deserves graying out, I'm always happy to elaborate on subj)
- https://redux.js.org/tutorials/essentials/part-2-app-structu...
But I try to stay away from it at work and I would rather push Vue 3.
There's few reasons:
- React does not really have a framework as good as Nuxt, which is light years ahead of the terrible mess of Next, and much more solid than Remix (which oddly comes also out with questionable stuff baked in)
- React is easy and funny to learn, but it's tough to master properly when it comes to few several key aspects like..There could be a PhD in hooks complexity, and all of that to avoid using class based lifecycle which was uglier but...much easier to manage
- Performance. It's just not good as on alternatives. At some point you scale, SEO and performance matter, React bites you back. There's many issues I could list from server to client side rendering and this will never be fixed due to how React's rendering works. Not only that but on React alternatives like Nuxt you end up thinking about performance way later
- DX on aspects like styling. I've tried everything and the DX of authoring and maintaining the style of react components is just meh
SPAs might be a good idea even for simple / low traffic apps, if you don't want to write and maintain a backend. SPAs are easy to statically host on a CDN. They don't technically "run" 24/7, they can't "go down" unless the CDN does. They can use a serverless platform API like Firebase and Supabase. They can be hosted for free at low traffic. Compare with rolling, monitoring and maintaining your own server, ssh-ing if it goes down, dealing with auth, containers, VMs etc. If you want to prototype, it makes much more sense to write a SPA.
At no point do you change your focus to what works best for the user. Who is the user; what kind of devices does he use; what does he want to accomplish on your website; what does he need to accomplish that; etc.
Additionally, there is an entire class of web apps that I wouldn't have written if they weren't SPAs. The luxury of uploading some files for free to an industry-grade CDN and using a ready-made backend of which I'm not the admin on its free tier allows me to write stuff that I wouldn't have even started if I had to rent a machine and spawn a server somewhere, with all the admin / maintenance costs attached.
Of course there is a class of people who don't want to run Javascript on their devices. I understand that and I respect that. I might be one of them in certain cases. But unless I'm writing life-saving software or I'm running a monopoly (which is generally not the case), their importance in my audience will be evaluated on a cost/benefit basis.
(+) If they are a monopoly, I would say that the problem are not SPAs, but the existence of monopolies itself.
The technology is always (or almost always?) their choice. However, if it is a public sector organisation, it owes it to the public to care about them, to be informed about devices they are using and the conditions they are using them in; and to strive to provide its services in the most accessible way. "How fast does a page load", "how fast does the page perform on users' devices once it's loaded", and "how gracefully it degrades under unfavorable conditions" should be important parts of the conversation.
Businesses in the private sector have fewer responsibilities to the public, and are primarily controlled by market forces; but still, it would probably benefit them to have similar considerations.
It's not a pleasure to work with.
I know quite a few programming languages, ~20 years of software development career. And React is the worst tech.
Don't get me wrong, but I wrote a lot of React code at work, and used it for personal projects (for example: make210.com)
But every time you touch React you're getting this distinctive "meh" flavor that tells you - oh yea, baby, it's because you're dealing with React.
When I was doing audio engineering professionally you would find a bunch of engineers who had the same sort of mentality about outboard equipment. Specifically modern outboard which uses switching power supplies and the like in order to reduce power consumption and, ultimately, the cost of the gear.
You can’t help but feel a lot of people feel threatened by advances in technology as their ability to gatekeep diminishes with every iteration. In the audio example you’d no longer have to spend thousands of pounds on a Neve preamp to get a professional sound. You can buy a focusrite interface for a couple hundred and have decent sounding recordings.
Likewise with React/Vercel/NextJS. With those advancements a person (I don’t say dev as the docs make it so most people can fumble their way around) can deploy a simple website in a week or less depending on their personal ability to learn. As such those who made a living overcharging to make a simple site for a local business are seeing their income diminish.
Just my theory, anyway.
And anyway... the weird parts about React are kind of weird... some people just like Svelte more ;)
0. People are coming to React after doing X years of that other thing, which was was not necessary related to user interfaces at all, was not procedural or reactive
1. People are super confused by something reactive and procedural, it feels too "complex" and something messy usually comes out of their fingertips
2. People think what if they sign for React, they automatically sign for react-router react-video-player react-redux react-custom-div-tag react-img and so on, bringing a ton of unnecessary dependencies to the project and crying out loud that this "whole React framework" is too complicated and nuanced
3. People don't bother going through official react handbook thoroughly and understanding that react is nothing more than a handful of hooks, which can solve every user interface problem in an effective way. Instead they watch 10-minute video on 2x speed which tells them to npm react-router, react-redux and react-custom-div-tag
4. People end up with a monster, which makes them cringe every time they are looking at it, and they can never ship it
5. People go and produce a big rant post to spread the hate with the title "How/Why I quit React and went back to Laravel, then finally shipped", sharing it here on HN
React is 10+ years old. Hooks are about five years old. There was react before hooks; and people who hate react don't always do so because they failed to learn the hooks api...
Also, the official react documentation is, predictably, a living document that keeps changing. I guarantee you that when react hooks were introduced in 2019, they were presented as a more convenient alternative to lifecycle methods, with a near-direct correspondence between the component lifecycle methods api and the hooks api. The useEffect hook was presented as a better and more powerful componentDidMount + componentDidUpdate combo. There was no talk of "you might not need an effect", which came out of several conference talks and culminated into a separate article in the docs. The first version of that "you might not need an effect" article appeared, according to github history, in 2022, three years after the early adopters had started using hooks including the useEffect. You were never supposed to update the state during render; now you are. You were always allowed to read component class properties during render; now with useRef, you aren't. And after all these years, react still seems to be in denial that sometimes you want some actions to happen only once over component's lifetime, upon its mounting; and you have to fight with the strongly encouraged StrictMode component for that privilege...
React pre and post 16.8 are two completely different libraries. I remember 2019, hooks we presented as a replacement to lifecycle methods and class-based components at all, not as alternative. The useEffect hook was presented as something which let's you split your code based on logic instead of component lifecycle, and few examples were there showing how the new effect concept better splits the async logic which was previously a solid mess inside the componentDidMount/Update.
>in 2019, they were presented as a more convenient alternative to lifecycle methods
Again, no one presented hooks as an alternative, it was strictly a replacement for class-based components which were obsoleted.
From the rest of it I see you have a very big problem with react, "you might not need an effect" article was written for folks like you. Update the state during render? what? if you need to read something during render you need to use State, and if you need a reference to a variable outside of React you use Ref; there is a clear way to make a side-effect happen only once over component's lifetime, which is to use Effect without dependencies. StrictMode component has no use other than debugging.
The two apis still coexist within the same library.
> The useEffect hook was presented as something which let's you split your code based on logic instead of component lifecycle, and few examples were there showing how the new effect concept better splits the async logic which was previously a solid mess inside the componentDidMount/Update.
That is exactly what I mean by the word "alternative". As in, previously, you achieved certain results by calling componentDidMount/DidUpdate methods; now, in order to achieve same results, you would use the useEffect in a certain way.
> Update the state during render? what?
See "Adjusting some state when a prop changes" section of "You Might Not Need an Effect"
> if you need to read something during render you need to use State, and if you need a reference to a variable outside of React you use Ref
Sure. But what if during a render you want to check something in the DOM (geometry of a DOM node or something). I do not think that pre-2019 there were any guidelines that you mustn't. There weren't any such recommendations after the hooks were released either, when all we had to go by was the hooks api documentation in what now is the legacy documentation site [0]. The caution against doing this only appeared in the new react docs in 2022. My point here is that the docs change, and the patterns of usage of the library change, and what was considered ok once no longer is. This might be why some folks are complaining, even if they don't fit the "don't bother reading the docs" profile that you proposed.
> there is a clear way to make a side-effect happen only once over component's lifetime, which is to use Effect without dependencies. StrictMode component has no use other than debugging.
StrictMode unmounts and remounts every component causing every useEffect to fire at least twice. Which means a useEffect with an empty array of dependencies will execute twice, unlike in production build in which it will indeed execute just once. This makes the code in the development mode behave differently than in production mode. This also makes useEffect with an empty dependency array incapable of guaranteeing that it will execute only once.
As for the empty array of dependencies to emulate the previous componentDidMount method, this was indeed the original message in 2019. I am almost certain — though I can't find this online now — that Dan Abramov subsequently tweeted to not rely on the empty dependencies array as a guarantee that the useEffect only fires once per component's lifetime.
[0] - https://legacy.reactjs.org/docs/hooks-reference.html#useref
>Dan Abramov subsequently tweeted to not rely on the empty dependencies array as a guarantee that the useEffect only fires once per component's lifetime
It is very strange that you can't find online such a non-sensical tweet from Dan, because in case of effect there is no component, and it's lifetime is non-existent, there is only function, and it can be called, and it might call a side-effect or not in it's execution, depending on X or nothing. He was probably explaining that a useEffect is not equal to a lifecycle method componentDidMount – and empty dependencies mean actual side-effect of your render function without dependencies, which you still need to clean-up properly – not the shortcut to the old "component lifecycle". After 2019 the whole concept of "mounting" and "unmounting" the "component" was obsoleted and replaced with just a function and it's side-effect, which was a dramatic shift towards procedural and functional react which does work at scale from the class-based lifecycle concept which failed at scale. For some people it is harder to grasp something procedural and functional, especially if they are used to think inside some other concept or paradigm, they mess up their one-way data flow, immutability, function composition and end up in pain using react, and it can be hated for that, i agree.
This is one of the big reasons why I personally dislike React and the community around it. They seem to envision at the start certain ways to do things, and push them to the point of being "this is how you do X". Then, after not very long at all, the old way is discovered to be bad and inefficient and buggy and hard to reason about or whatever, now do it this other way. Repeat three or four times until a new API is created or something.
This also means that going from project to project can feel very whiplash-inducing. The code you find is not even dependant on the version of React that's installed, but on how the community was feeling about the "best practices" around the time that particular project was started.
I remember when render props were a thing. Then I remember when they stopped being considered a thing and now the new thing to do was HOCs.
Things like React Router also being wildly different between versions, or at least v3 -> v4. I remember needing to find out how to achieve certain behaviour with v3, only to then try to find that the docs only existed for v4 (which was the newest at the time), and addons that helped me with my original problem also only existed for v4. (Then React Router was no longer the Best Thing, so let's all switch to Reach Router... then back to React Router when it was again considered the new hotness. I may have forgotten one or two others in there, I just stopped paying attention around that point.)
Another example is CSS scoping, which is a complete non-issue with vanilla Vue and Svelte. But in React land you have styled-components, emotion, styled-jsx, and who knows what else in which you don't write CSS, but JS that looks like CSS but not quite, enough to throw me off every single time.
The whole periodic shifting of opinions about useEffect from "this is your componentDidUpdate replacement" to "use a linter to warn you about the footguns that we can no longer fix, also use one of these hooks instead" is just one more thing that adds to the frustration of having to work with a React-based project.
I'm actually starting to wonder if Facebook isn't so much "writing" React, but "discovering" it. Much like how we didn't quite invent fire, and we had to figure out how to use it properly over many, many thousands of years.
I feel sorry though for someone getting into frontend dev now.
> is a new hook to order Actions inside of a Transition with access to the state of the action, and the pending state. It accepts a reducer that can call Actions, and the initial state used for first render. It also accepts an optional string that is used if the action is passed to a form action prop to support progressive enhancement in forms.
I’m pretty sure it’s a cool feature but, what a mouthful. Imagine you decided to start developing websites today, how do you even start?
EDIT: React is still an exceptional framework and this release is certainly an improvement.
My criticism is more FE development in general not just React.
It sounds bad, but if you can, do oldschool SSR with HTMX or the like.
It's sooooo much better. I was paid to develop frontends in React for 4 years, I wrote my first website in 2005... I am currently migrating one client project from React to HMTX and it's sooooooooo incredibly much better.
There are less bugs, less footguns with wrongly applied hooks...
If you need to do CSR, use Solid or Vue, but don't do React.
If you have no say in it: good luck!
Do you mean the whole field, so from B2B SPA apps to personal blogs? "If you want to replace jquery, use Vue!" would be more helpful to understand.
The problem is that we don´t know if the advice comes from a "bootcamper" that has only learned Javascript. You know, some people manage to build low-interaction sites that will render a blank page when Javascript is disabled.
The "why" is also of interest to see if the advice is applicable. If not react, then why not preact for instance?
Disproportionate amount of energy I would rather spend learning JavaScript, something that would last.
Using React since 2013. Each release is an excitement, until I realise some chunk of concepts which altogether took months to fully grasp, are gone. Some even needed to be unlearned.
A lot of abstractions.
React doesn't make you a better developer, it makes you a better React developer.
I don't feel that with Vue. I don't feel that with most libraries I use.
React's pure component functional style translates really well to nearly every other type of software development.
I say this as a big fan of React, and I'm hoping the compiler turns out a success.
The non declarative aspect is a problem though, with v19 it now means unbelievably large PRs and time spent to refactor will take place for migrators. Declarative would at least reduce reduce that pain.
https://vladislav-lipatov.medium.com/solidjs-pain-points-and...
So it's gotta be something else that makes it so popular.
React's goal isn't to make you a better developer though. It's goal is to make it easier to build non trivial, stateful applications
And anecdotally, if your team is not ready/willing to dig in react, all its benefits will fail to materialize, you'll have a bunch of patched up libs and components trying to do what htmx or similar seem to offer (async actions over REST) for just a few lines in your html template.
9 years of professional experience.
Having worked and paid to do so with Java, Scala, Kotlin, Python, JavaScript, Typescript, Python
Been working with Rust since 2015, have prior experience with C++, had to work with C, Haskell and logic programming (not prolog) at University.
Also did C#, Golang, Lua, Zig and many more.
Does that give more authority to my statement? I sincerely hope not!
FE tooling is never a one-size fits all thing like Postgres, but people want it to be (god help you if you have 2 different FE libraries that serve different usecases, even though 90% of the time you just need simple tooltips or a multi-select box that play nice with static server HTML) and the cost is giant, unmanageable, extremely expensive piles of JS where the entire frontend is pushed inside of it.
I think the web technology and the kits that sit on it are rather obtuse because they really are swimming against the tide. I commented about VB a few weeks ago and how much better the paradigm was some 30 years ago. But that was a purpose-built tool for programming a purpose-built GUI API. React et al. are still contending with turning typesetting into general purpose software. Despite that, react does a pretty good job.
It's also about know-how. I can go get a programmer literally anywhere that can built something with react, so even problems that can be solved without are going to be solved with it.
No complaints from me, really. Everything is a little excessive. I just came across an app to order ice. I can't imagine that's really making anyone's life easier, except for maybe its developer.
1. Beyond self-learning, there's two types of education. Formal, college education that delves deep to both the CPU level and mathematical proofs of correctness, and coding bootcamps which teach how to do things, but little about how things work.
Frontend isn't taught in formal college education, so there's a big void in industry knowledge. Some people learn about compilers, interpreters, have used GDB and implemented malloc for school, but they aren't the ones doing frontend. Others are doing frontend but never think about memory usage, closure scopes, or garbage collection.
This leads to bad frontend code, that misuses resources.
2. JavaScript long had fame for being a "toy" or "joke" language. I noticed the tide slowly change by the mid 2010s— that's not that long ago.
Proportionally and compared to other technologies, how many engineers have had time to develop long careers, learn from mistakes, and become that serious, dress-shirt wearing, super-senior engineer sitting at the back of the room making sure young developers don't get too unhinged? This proportion is probably especially stark if you consider just how in-demand web development is.
This leads to bad frontend code, that misuses resources.
3. Finally, with the two above in mind, re-writes. Unexperienced teams are the first to opt for re-writes. It's a story as old as time; "we don't know how to fix A, so let's instead build a brand new thing B, which works differently to A and thus won't have its problems".
Re-writes always go well at first, because the fresh codebase will be smaller, faster, nicer and because everyone is especially cognisant of the problems A had, which are very much not present in B since it works differently.
Eventually of course, B grows bigger, and gets permanent hot-fixes, its requirements change, and bugs start to surface that nobody bothers understanding. A is also far enough in the past that nobody is thing about the problems A had anymore, and has more mind-space to notice the problems that are unique to B.
But before that happens, you get this sort of comments.
One example from my own experience was a team that inherited a service that had already seen a major rewrite/refactoring to be prepared for requirements that the old team knew with certainty was coming. The new team created a new service that barely covered the needs that the company had at the time, and claimed that the new architecture was flexible to cover any future need (without actually investigating the needs that were already known). When they were tasked with supporting the new requirements, the end result was more complicated and less capable than the old service.
What does churn is the tooling (e.g. abandoning Webpack for Vite). But the actual API and syntax has remained virtually unchanged. You can still write and use class components today. Hooks themselves are nearly 7 years old at this point, with no sign of changing. You are not required to use "server components" or any of the new features in React.
Meanwhile people in this thread recommend "simple" alternatives like Vue that produce breaking changes so massive it splits their ecosystem in half.
It's a form of technical smugness that pervades this site for any frontend JS thread.
You rarely see frontend devs criticise backend devs on their tech stack.
If you use just React I'll support you until the end of time but haven't seen a shop yet that does. I'm not saying use HTMX, if you have the choice go with just React over HTMX because it's still in flux.
Just React << HTMX < React with Friends.
It's the advice from POODR that's stuck with me forever, an objects dependencies should change less often than the object itself.
If you think rotting sounds too negative how about "maintenance unfriendly."
If you only want minor changes, don’t install new major versions.
It's just not true in my experience.
And React is worse than the alternatives. All it has going for it is the huge ecosystem.
eg: <todo-list><%for...><todo-item .../></for%></todo-list>
I've poked at `lit`, read through `htmx`, but really what I want is "custom elements" (including visual styling) on the front-end that I can map back to JSON on the backend.
The CSS side nudges towards tailwind (or similar), and modern (raw) CSS has undergone so many feature extensions and new capabilities, it's tough to find a good "modern" guide for building with it.
It just feels like there's a missing piece in-between: `let contact = new LdapContact(...)` and `<contact-summary .../> ; <contact-detail .../> ; <contact-search-result .../>`.
Vue has come closest, and setting aside a super-complicated "WebApp/SPA" with a ton of interactivity... what's a comfortable, modern, low-ceremony way to get to that?
Easier said than done.
There're still many high quality libs for React that are not available for vanilla JS or other frameworks. E.g. https://reactflow.dev/ (yes, they have a Svelte version, but not as feature rich).
Vue comes very close, though.
HTMX is just "replace this with response", you'll still have to write all the CSS classes, manually add them to all the elements, do animations yourself etc. I like HTMX, but I am tired of backend and hobby programmers shilling it at every opportunity. Try to write a reasonably complex website with it and give it your friend to maintain and improve. You'll understand why frontend frameworks exist. HTMX sends you back to the HTML-in-PHP ages with homebrew ORMs and what not, because there's no unified way of doing things.
If you are bemoaning the lack of prefab component libraries, well that's how backend development goes. Everybody and their dog has a backend stack and HTML generation system they like, and then eventually maybe some component libraries will emerge for the popular ones. That's the tradeoff for the freedom htmx gives you to work in any backend. You write some components yourself. Not the end of the world.
With something like MUI, everything is where I expect it to be. That consistency lets me focus on learning the business logic, addressing critical bugs, and thus making meaningful contributions.
- will my client have problems finding someone that speaks Czech/Slovak and also knows DaisyUI/HyperUI/HTMX/Django? - are those techs gonna be maintained in 5 years? - what's the bus factor on the techs? Is it several people's project or a one (wo)man show?
All while there's React+<one of the big component libraries> right at your disposal...
HTMX philosophy is to be timeless and agnostic as HTML is, is just a nice extension on top.
Meanwhile, I have v0 generate the whole skeleton for me, with composable reusable components, and just got the API done.
Like for example: https://shoelace.style/
Most React apps need a backend too.
We did that for a long time with Perl/PHP/ASP/JSP
I wonder why we stopped doing that? I'll just wait a few decades of your FE with this until you figure it out scnr
Does it? To me, it seems more proof that software development trends are cyclical. It's also just not all that apparent that things like HTMX are all that popular. React is much more popular than any of them, and then JQuery remains even more popular than React, at least in terms of finding it on the web.
Working with XHR sending full HTML responses, it's pretty clear to me that there's some major tradeoffs to this approach. The payload sizes are larger and interactivity is dependent on round trips to the server. so you're increasing server load and are increasing payload sizes to save on client side processing.
If your views are data driven, then there's plenty of cases where you may want to have interactivity. filtering or sorting results, for example. So you click a column header, then you're sending another request to the server, asking for a new table with the newly sorted rows, it renders it, sends it back to the client, and then replaced the entirety of the table contents with the new contents. and then htmx does some magic to make it behave closer to native HTML (like enabling css transitions on replaced elements, for example).
Storing the state client side, you can perform a lot of these transformations without talking to the server again until you want to actually change data.
I'm all for sending plain html from the server. If your views are static and largely unchanging, then sure, by all means, send it over. You don't need a JSON response to render a blog post on the frontend. But as soon as you want any sort of interactivity in your forms or data views, then you probably don't want to make every interaction a round trip to the server and then you're back at having to think about state on the client, at which point objects in JS are just going to facilitate your needs better than html elements.
> Storing the state client side, you can perform a lot of these transformations without talking to the server again until you want to actually change data.
Only if you're only working with a tiny amount of data...
For example, say you have a dataset with 10k records. You're not going to want to send that all to the client so it can sort it locally. Much more efficient to send just the first 100 or whatever results. Then when the user clicks the sort button, ask the backend to re-sort it and give you the first 100 results again.
Bonus: those 100 results are already formatted as html table rows and htmx easily slots them right into the correct spot on the page.
But even with a modest 100 rows being retrieved, the payload size of fully rendered HTML is generally going to be substantially larger than JSON. These add up quickly when you're making round trip requests to the server for interactivity, especially if it's something like reordering tables.
This is a clear tradeoff and it's why we see trends like this oscillate between client-side and server-side.
I think React is seeing the downsides of being entirely client-side, which is why there's so much development into server side components. Conversely, things like HTMX are tackling problems of handling local state, client/server side caching, and well, payload sizes.
Substantially larger? No, I don't think so. Maybe slightly larger, but if you are compressing your responses (a best practice), there should not be a significant difference between them. And, while in a theoretical perfect world you send exactly the JSON needed for each response, in real-world conditions JSON APIs are quite often overfetching and making too many calls in the first place. Evidence: just look at any typical React-based webapp accessible to the public.
Meanwhile with htmx you can render and send the exact HTML you need for the response, and any overfetching is immediately obvious because it's all shown on the page.
Are we talking about this in an absolute sense? because an html payload whether you compress it or not is generally going to be larger. It obviously depends on what your html looks like, but even if you only are using minimal class names and aria properties, it's still going to be larger than JSON in almost all cases. As in conservatively 50% larger but realistically even more than that, just based on admittedly rudimentary experiments. That's after minification/gzipping and tabulated data is best case scenario for HTML with the small element names (tr, td).
Does that actually matter? Maybe, maybe not. As you said, plenty of real world cases of JSON APIs that are sending excessive data or making calls to the server too much.
...but with things like HTMX, you're either hitting the server or you're using client-side processing of some sort (at which point we're back at why aren't we using something that effectively handles other frontend problems?). I also still think there's rather large downsides to having part of your frontend being handled by the responses from the backend, even if you're using only using full stack developers.
Unless you're using tailwind or some other variation of inline styles, I don't think a typical formatted <tr> is going to be much bigger than a json record anyway. It might even be smaller if the json includes extra attributes that don't make it out to the html.
But I agree that if you know you have a tiny amount of data and you don't want to involve a server then it would be better to do the entire interaction client side. But nothing prevents you from plugging in a small client side lib (not react) and using server-side for everything you can.
You can build single-page applications with React, you cannot with HTMX.
Irrelevant to the conversation.
GP said:
HTMX is not a replacement for React -- HTMX + a backend is
So if you think that's not true because React can build SPAs and HTMX cannot, take it up with them (maybe you replied to the wrong comment?).
You stated: "Most React apps need a backend too."
But in reality this is irrelevant to the conversation, because the top post was asking if comparing HTMX to React is like apples to oranges, which it is, because both tools accomplish different things with completely different feature-sets.
A good example of this is the implementation of TodoMVC. [1] React's implementation can live completely in the browser, and even be stateful. [2] An implementation with HTMX requires a server to handle templating/rendering. [3]
[2] https://github.com/tastejs/todomvc/tree/master/examples/reac...
htmx-powered applications can be local-only via service workers[1]
i think there is a sense in which htmx vs. react is apples to apples, in that in the common case they are used to build web applications that talk in some manner to a back-end system. On the other hand, it is true that react does require additional support code in order to do that communication.
Regardless of that latter fact, and the fact that htmx does not require a server, there is a large overlap in practical applications that might be built with either, so it is good to know the strengths and weaknesses of both for comparison.
[1] - https://developer.mozilla.org/en-US/docs/Web/API/Service_Wor...
I mean, I guess if you consider me opening an index.html file in my browser requiring a backend in that my desktop operating system is the "backend server", then yes, but that's not what I was referring to. I don't think most folks would consider a CDN to serve static assets to mean "your React app requires a backend" in the traditional sense -- but that's a game of semantics.
> htmx-powered applications can be local-only via service workers
Do you have any examples of an HTMX app running completely client-side using service workers? Funny enough, the only example I found online ends up using Preact to render templates in the SW, but as a whole, this looks less ergonomic than simply using <insert JS library here> to build a SPA: https://joshi.monster/posts/serverless-htmx/
> there is a large overlap in practical applications that might be built with either, so it is good to know the strengths and weaknesses of both for comparison.
I could agree with this. I only care that people understand there are tradeoffs.
In the browser we have no choice, but I prefer to prevent that accident from spreading to my servers.
The picnic example would be more like mixing them up though ;-)
HTMX allows you to learn the very basics: the HTML which is almost verbatim turned into DOM which the browser renders. It's the FE. Everything else is layers upon layers of abstraction which ultimately compile down to the DOM representation of HTML.
...or to put it differently, quoting HTMX's author: using HTTP to transfer HTML? How queer!
Avoiding the most popular front-end tech (or any tech) is a good tip for those who want to play Finding a Job in hard mode.
Being mindful of the never-ending-nirvana frontend spirit of churn, and after doing web development in VBScript, JS, JQuery, Mootools, Applets, Actionscript, YUI/Ext/Sencha, Backbone, Knockout, Angular1, Angular2, React, Vue1 – I'd say try Flutter. It's genuinely a breath of fresh air.
Except... Dart. If only Flutter was in Typescript it might have been a bit closer to nirvana. The Dart part is still keeping the frontend spirit of churn alive.
It's an interactive business analytics, one of those use cases where an SPA makes sense — 15 years ago it would have been a native desktop application.
We just follow the usual guidelines, no extraordinary optimization techniques or anything like that.
The main issue is React forces you to tell it which components to re-render. This causes a bloat of ceremony that makes it endlessly annoying (in comparison to global redraws) to write in.
That's a really weird statement, do you keep your application state in a mutable data structure instead of immutable? Do you know what a pure component is?
I most certainly don’t.
As someone who has mostly done low level coding and used to generally dislike my few interactions with web frontend development, I was extremely surprised when I picked up React a few years ago for a personal project.
The whole thing feels like actual proper development. What a breath of fresh air compared to the situation before.
In professional projects with teams of developers contributing and PMs wanting feature flags, tracing, complex behavioral logic, it gets crazy.
Been there and done that with and without. Junior (and Senior) devs fundamentally don’t read the docs. That and requirements churn are the problems.
Given that, it ends up so much better with React.
Easy: By not using that optional feature.
If you’re like 99% of developers you really don’t need stuff like that until your app reaches a certain stage of growth, if ever - and React doesn’t force it on you.
> asyncio.as_completed() now returns an object that is both an asynchronous iterator and a plain iterator of awaitables. The awaitables yielded by asynchronous iteration include original task or future objects that were passed in, making it easier to associate results with the tasks being completed. (Contributed by Justin Arthur in gh-77714.)
"I’m pretty sure it’s a cool feature but, what a mouthful. Imagine you decided to start developing python scripts today, how do you even start?"
Async, await, iterators, futures etc. are pretty much standard constructs in almost all programming languages / concurrency frameworks.
Whereas Actions, Transitions, Pending State, Reducers etc. are React-specific idiosyncrasies.
I guess that's the main issue people have with React, when you learn it you have to spend so much time to learn all these React-specific constructs and idiosyncrasies that are not transferable anywhere else.
Similarly, wether they are React-specific idiosyncrasies or not, one shouldn't assume people need to jump straight into Actions, Transitions, etc when first learning React.
Have you tried using v0 to generate a layout and a barebones application? It saves so much time. No more hunting for templates/themes, no more mocking.
But I also _spent_ a bunch of time as soon as I needed something slightly different to OOTB (or sometimes just wanted to understand how a thing worked better). At that point I ended up digging through Radix code, React library documentation where there were frequently multiple ways of doing the same thing and I had no idea which was "best". I had to delve into some of the more complex (to me, as a newbie) patterns like forwardRef. And this was all for a very trivial site/app that needed some form interactions.
My takeaway at the end was, I'd learnt a bunch of new stuff, which was the point, but that was all workarounds for dealing with the complexities introduced by the tools which were meant to simplyfy my life.
Perhaps for large projects with multiple devs, they bring efficiencies of scale. I think for my next solo project I'm trying Rails or Django with htmx.
However, in solo projects, I want to spin something up quickly. I don't want to spend my scarce weekend time designing yet another date time picker. Or having to write hackish CSS to try and make whatever time picker library I chose to match the CSS of Bootstrap. And then everything falls apart because some other library does not fit into the overall style (looking at you DataTables). In React land, I don't have to worry about this. I just throw components together, link it to my API where the show real is, and call it a day.
UIs are just UIs. They should be plug and play. So much time is wasted redesining data grids and data tables and pickers and filters for the 1000th time.
Even the reference section of the site makes clear how far down the priority list the advanced hooks are.
My response has been to avoid SPAs as much as possible. YAGNI! Just use boring forms and server responses. Some component libraries can be server-rendered, minimizing the JS payload while giving you some primitives to build off of. Components are a really nice abstraction even in a pure server context. You can contain the goopy Tailwind code a bit.
It's not all bad. Astro seems pretty nice so far!
Why would that be true? Often people don’t know what they need to solve a particular problem.
You learn vanilla HTML/CSS/JS (I think Mozilla has good courses on those). After making a few websites that way, you learn Svelte and you live happily ever after.
Avoid React, NextJS at all cost especially since many of these new frameworks actively try to screw over new developers with PaaS.
I think React peaked with hooks around 2019. I write most of my front-end with the smallest 'React-like' library possible (Preact) using only functional components, and with as little 'magic' from useEffect etc. as possible.
I like to stay close to 'raw' HTML/CSS/JS when possible, but the web platform APIs are just a little to clunky and verbose for me without the JSX abstraction.
So new projects have to actively not follow the recommended approach in the docs if they want to use vanilla React.
But otherwise, Svelte has a very low surface, everything else is just standard vanilla JS/Html, also one thing that Svelte has over other frameworks is that vanilla JS libraries just work, no need for a wrapper any.
I don’t get how people get so paralyzed of making the most optimal decisions all the time that they end up doing nothing or procrastinating by convincing themselves they need to learn some other basic framework instead.
One mark of a framework with a future is that it supports its past. A framework with a lot of breaking changes is one that is not mature, and may never be mature.
Even with the substantial shift in React from classes to functions and hooks, old code still works. You probably don't want to start writing class-based React, so you want a tutorial written in the last 5 years, but those are hardly new and certainly not specific to React 19.
Getting started with Vue was so much easier, I never looked back to React.
I still have to deal with React codebases, and every time I do I dread it.
I presume most people learn to deal with that when they're like, twelve, or something. Otherwise you just live with constant regret and FOMO.
I'm an embedded dev so I've so far removed from web dev, but recently started looking into learning web dev for some personal projects. My god what a mess.
Any learning resource for a single topic , like javascript, Flask, CSS can't seem to stick to what it's trying to teach and insist that you start importing other libraries and frameworks. Most of the time they're not needed and the author just assumes that you understand this other library in order to continue following their examples
So you google how to use that library, but the learning resources assume knowledge of a different library...
When all the resources of just plain javascript and plain HTML/CSS. I don't want bootstrap or react, I just want to learn the fundamentals to build upon
As far as I know this usage ultimately derives from HTML `<form action={}>`.
FWIW I liked Redux enough that I once half-reimplemented it for Brightscript so the UI guys would have something familiar to work with when they had to touch Roku apps. I always taught Redux initially using different terminology, though, because I found that most of my time learning it (which, mercifully, still wasn’t that long, because it’s small and pretty sensible) was figuring out the vocabulary (“do… do they just mean ‘event’? Well if so surely they’d write ‘event’, so I must be wrong…”)
And yeah, half of Redux's terminology is simply because the existing Flux Architecture libraries from the prior year all used those terms. There were several debates in the issues about whether to name them "actions", "events", or something else, and the conclusion was "let's just stick with the existing Flux terminology":
- https://github.com/reduxjs/redux/issues/891#issuecomment-147...
FWIW, as I've revamped the Redux docs over the years, I have specifically made sure we describe the "actions === events" aspect:
- https://redux.js.org/style-guide/#model-actions-as-events-no...
- https://redux.js.org/tutorials/essentials/part-1-overview-co...
Thanks for the work on a project that I got good use out of, and happen to personally like more than I do most software.
With HTML and CSS. And you don't touch JS until you understand the fundamentals of those. And only after those three do you touch a FE framework.
I'm not even kidding either. Whether its React, Angular or any back-end driven templating, those things are all abstractions over fundamentals.
You'd slap together a Jenkins/Jekyll site and host it on github for free. It's easier now to set up a website than ever. But yeah that React sentence is pretty difficult to gronk.
You start where the docs say to start, https://react.dev/learn which wouldn't be mentioning this advanced feature, just like pretty much any tech. Reading postgres, python, etc release notes will have a bunch of scary sounding new features to a beginner, but those won't be making their way into the "Get started" section
It's a full-stack JS framework with its own components library that uses plain HTML, CSS, and JS (and has dead-simple, obvious APIs for implementing more advanced logic like state and event handlers). It's a logical next step from learning web dev fundamentals to building full apps.
How? Please be specific, because unless you're altering the source (which I'd be very unpleasantly shocked by), your use of untagged template strings makes it fundamentally impossible to mitigate such stuff, short of forbidding characters like & and < and " from data, which would be insanity. You're mixing template and data willy-nilly.
Developer controlled code at the component-level is assumed trusted, however, there are three mechanisms for handling escaping/sanitizing on the server:
1. There are helpers built in to the API (you can conditionally enable sanitization depending on need) to handle sanitization and helper functions built-in to the server-side to do one-off escaping/sanitization for HTML.
2. Query params are sanitized automatically to prevent injection.
3. To prevent unescaped HTML in data from breaking renders, I base64 encode it before sending it to the browser.
This approach to escaping is by design as some use cases call for sanitization (they're rendering user-generated data) while others do not.
You're welcome to audit the source and see if I missed something or make suggestions on improvements.
This is a phenomenally bad idea. By escaping things willy-nilly you’re making life much harder, and vastly more error-prone. You can only even vaguely sanely do such things with the support of a better type system than you have available to you. You’re encouraging storing escaped HTML in the database; exposing an API that HTML-encodes all strings; you’re misusing the term “sanitise” (sanitising is fairly consistently used to mean stripping control sequences, not escaping). This is a disaster. Given that you’re working in JavaScript, you need to use something like JSX or equivalent functions or tagged template strings, so you can escape only as appropriate. As it stands, I would genuinely expect to be able to find trivial functionality and/or security bugs in practically every decent-sized Joystick site involving user input.
One specific technical bug: https://github.com/cheatcode/joystick/blob/canary/node/src/l... tries to escape &<>"'`= but will replace backticks and equals signs with “undefined”. Defining HTML_ENTITY_MAP in a separate file was a mistake; you’ll hopefully never refer to it anywhere else, and separating it made such an error easier to make. (Incidentally, backtick and equals sign have never been useful things to escape in HTML. Truthfully, & and < are all you need in HTML text, and & and " in double-quoted attribute value. If you want to support XML, then escape < and > everywhere as well. But nothing beyond that is useful.)
Here's an example repo: https://github.com/cheatcode/escape_test
And example text I used to test: https://gist.github.com/rglover/c75e37b526d864313b461d38195b...
> You’re encouraging storing escaped HTML in the database
You can store unescaped HTML in the database and upon retrieval, escape it (see the linked demo repo above). You hypothetically could store escaped HTML, but you'd have to show me where I'm encouraging it (I think what you're saying is that because you can do it, I'm encouraging it).
> As it stands, I would genuinely expect to be able to find trivial functionality and/or security bugs in practically every decent-sized Joystick site involving user input.
You're welcome to audit it, but please, actually test it by building something and then provide an example repo. Make sure to use the canary release as that has the latest changes. If you email me (ryan.glover@cheatcode.co) I can give specifics on how to get set up.
---
FWIW, this isn't a productive way to point out issues with a project. A PR with comments is preferred.
Your particular angle on it might be novel, I’m not certain, but only because it’s an even worse idea. Formerly, there was a simple rule: remember to escape data when emitting HTML. You’ve replaced that with something complex: some things will be entity-encoded, and others won’t; and often you won’t want things entity-encoded. (You’re inappropriately tying API to HTML, by the looks of it.) This is just a bad abstraction that makes errors sure, and errors will lead to some mangled text in all cases, and security bugs in some cases.
It’s very similar to how the consensus is now well-established (though it’ll take plenty more time to be fully applied) in memory safety, a related security field: avoid languages like C, they’re too dangerous, use memory-safe languages instead.
Another well-established principle: parse at input, let your system deal with data, and serialise at output. Your approach instead serialises at input—and that only most of the time—and hopes you never need to parse.
I’m certain that I’ve upset you, and I’m sorry about that, but the approach really, truly is that bad, and I did just want to appeal to you to think it over. Look, if you can find someone experienced in web security and frontend framework design and things like that, preferably who’s been doing this for fifteen or twenty years, present the whole design to them, and see what they say. I genuinely expect horror.
As for your changes to escape_html, I’ll just ask why? because you’ve compounded the error. There is no plausible purpose for all the additions you’ve made. By encoding, you declare intent to feed the value to an HTML or XML parser in data state, single-quoted attribute state or double-quoted attribute state. In none of those states do any of these additions achieve anything. And if you’re making them for some other purpose, then you don’t want the HTML escaping in the first place.
Fifteen years ago, I would encounter both double-escaped HTML and entity-encoding in non-HTML contexts, far too often. Now, I feel like it’s years since I’ve seen such a thing, outside of text/plain parts of emails (but developers and marketers are frequently awful about text/plain parts).
The only advantage I can see in entity-encoding more characters, especially all normal punctuation, is that bad escaping is going to be caught earlier. But I say, if you reckon those worth escaping, why not go the whole hog and .replace(/./ug, s => '&#' + s.codePointAt(0) + ';')?
I’m not sure what your experience is, but the impression I’m getting is that you’ve been largely just JavaScript. A lot of the problems you’re producing were best-known through PHP, and better type systems are a large part of the best solutions to these things. If I’m sounding you out correctly, I’d recommend that you look into and learn some strong statically-typed language, preferably one with algebraic data types (also called sum types). Rust has been my own preference for the last decade, but there are plenty of others that would guide you in similar lessons, like (in no particular order) C♯, Swift, Elixir, Kotlin, Scala, Haskell. (I don’t include TypeScript in this list, although it could definitely help with some of the lessons, because it’s too compromised by JavaScript limitations.) If you haven’t had any of this sort of experience, getting it will help you to write better JavaScript, and make better systems.
—⁂—
Now, for a specific matter:
> You hypothetically could store escaped HTML, but you'd have to show me where I'm encouraging it
<https://docs.cheatcode.co/joystick/node/escape_html#:~:text=...>
(And if you unconditionally entity-encode query string parameters… I don’t even want to think about the implications of that.)
I would also point out that https://docs.cheatcode.co/joystick/node/app/api/sanitization says:
> Sanitization is the process of scrubbing unexpected or unwanted HTML tags from the values returned by your API.
But this is not what you’ve implemented. You don’t actually scrub, you entity-encode.
If there's something specific that you can point me toward, I'll take a look and work on improvements. But honestly, the majority of the above reads like you just want me to feel bad and quit (and again, doesn't provide a clear answer to "what to do instead"). If you can succinctly explain why my approach is bad and offer examples of fixes (in relation to the current design of the component system), I'm all ears.
By doing escaping solely on the server, it creates two problems:
1. You're leaving escaping up to good behavior which will inevitably lead to some value that needs escaping being missed.
2. You create a double-escape problem on the client as you may need to render the raw output (e.g., rich text) and a server-escaped value would require an "unwinding" on the client.
Beyond this, I also corrected what you pointed out in the docs as that was the opposite of what I intended for that function.
I think the approach will be to do some automatic escaping on the client and then pass some special functions to the render() method on components to allow rendering raw, unescaped user data (i.e., a dangerouslySetInnerHTML equivalent).
If there's anything else specific that you'd add, let me know.
---
You seem like you have a lot of knowledge, but in the future, if you want someone to listen and comprehend what you're saying, avoid the fatalistic, theatrical language and emphasis.
Your point is incredibly helpful and showed me something I wasn't thinking about, but the way you communicated it almost made me ignore it.
If the above isn't correct (or misguided), it'd be best if you just plainly explain why and what should be done instead (and not a wholesale "this could never work, burn it down" response).
Not with React?
Seriously, if you are starting developing websites today, the first thing you need to do is learn the web platform: html, css, javascript (probably typescript as well while you are at it), svg; and some basic server-side stuff. React is for when you get pretty comfy with those.
The model they've chosen is the opposite of what one would intuit and because of this model, it is necessary to manage state a bit differently in React compared to Vue or Svelte.
This is genuine question; I've not used Vue or Svelte.
Vue and Svelte don't work that way.
In a Vue SFC, this is fine:
<script setup>
let counter = 0 <-- This code only runs once
watch (someRef, () => { <-- Only this code runs when someRef changes
counter++
console.log(counter)
})
const fn = () => { ... } <-- Normal functions are stable
function fn2 () { ... } <-- Stable as well
</script>
Basically, it behaves like you would expect normal JS closures to behave because the `setup` function is invoked only once. When `someRef` changes, only the `watch` function is executed (this is also why Vue and Svelte perform better because they can execute a smaller subset of code on updates).JS and DOM itself work with the same conceptual model, right?
<button onclick="handler()">...</button>
<script>
let counter = 0 <-- Allocated once
function handler() { } <-- Only this code is executed
const fn = () => { ... } <-- Allocated once
</script>
In React, this (obviously trivial example) doesn't work: export const App = () => {
let counter = 0 <-- New allocation on each render
const fn = () => { ... } <-- New allocation on each render
// ...
}
Because the entire `App()` function gets invoked again. So you have to use hooks to move state out of the path of the component function because the entire component function is re-invoked. Imagine if React, instead of invoking the entire `App()` function, only invoked the code affected by the change as captured in the dependency array. That's how Vue and Svelte work; the same way that a handler function via `addEventListener()` only executes the designated handler function. React does not work this way. Think hard about that and how React is conceptually opposite of how events work in DOM itself.This difference in design means that in Vue, there is -- in practice -- almost never a need to do manual memoization and never really a thought of "where should I put this"?
It might seem obvious here, right? if `fn` has no dependencies on the component state, then it can just be moved out of the `App()` function. But this is a common mistake and it ends up with excess stack allocations (also why React is generally the poorest performer when it comes to memory usage).
React's model is a bit of an outlier for UIs which generally assume state encapsulated by a component is stable. React says "no, the component function is going to be invoked on every change so you cannot have state in the component."
A different way to think about this is to go look at game engines or desktop UI frameworks which render stateful objects onto a canvas and see how many game engines or UI engines assume that your object is recreated each time. This is certainly true of the underlying render buffer of the graphics card, right? But generally the developer builds on top of stateful abstractions. React has, in fact, moved the complexity onto the developer to properly place and manage state (while not being faster nor more memory efficient than Vue or Svelte).
I believe that a lot of React's expanding complexity flows from this design decision to model inherently stateful UIs in a "pretend everything is a stateless function" way because it is fundamentally playing opposite day against the underlying JavaScript and DOM.
Another thing I found un-intuitive with React is the state of multiple instances of the same component. The useState() hook basically references some global state in the global context. When the component is used in multiple places, i.e. <my-comp></my-comp> <my-comp></my-comp>, the useState() hook inside is called twice and somehow they get a different copy of the global state. I know the magic of the global array to track the states. It just feels a bit too magically.
I chuckle it's claimed that React component is functional. And cringe whenever people put out the UI=F(props) statement, as if calling F with the same props multiple times getting a different set of state values not the anti-thesis of being functional.
https://news.ycombinator.com/item?id=37349286
great explanations, thanks!
Probably with something simpler like Alpine.js, or even JQuery. No beginner is going to be building the kind of web app that requires such a heavyweight framework like React. Don't bother with it until you know you need it.
The quality expected of apps over the last 20 years has skyrocketed, and the tools to handle those requirements have gotten increasingly complex.
https://react.dev/blog/2024/10/21/react-compiler-beta-releas...
That said, it doesn't change the APIs included in React itself, or the overall usage patterns. Ultimately it rewrites your component code to add a lot of conditional comparisons to see if props or state values changed, and uses that to trigger React's existing rendering optimization behaviors.
Long-term, I expect that the React Compiler _will_ result in a significant change in the DX for using React. React's default behavior has always been "re-render recursively regardless of props changes" [0], but people often assume it's "only re-render the child if the props changed". React Compiler actually makes flips React's default behavior to make that a reality.
[0] https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...
When not, I focus on backend and devops instead.
Although some SaaS products make our life harder, with React only SDKs.
Yeah. For the last decade or so frontend has felt like standing on shifting sands.
In part it's the ecosystem and entangled deps but also because JS frameworks are really still figuring it out. A couple of years ago I was hoping we'd reach some sort of stable plateau but it just keeps going...
"the DOM is slow we need a VDOM!"
"the VDOM wasn't such a good idea... signals with fine-grained reactivity is really the solution for DOM udpates!"
"oh wait but we now need a compiler!"
"oh wait there's too much JS now... we better move stuff to the server and do SSR with full page hydration!"
"maybe full page hydration wasn't such a good idea... we now need islands!"
Etc.
Don't get me wrong, each of these steps makes total sense. But we're getting into this uber complex solution that involves so much stuff across the whole stack... and it's not even clear to me that running JS in our servers was such a good idea to begin with.
I don't know, there's been a lot of stuff since 2014.
In client-side React we've seen stuff like react-query, mobx, etc which weren't there a decade ago. Back in 2014 everyone was still using redux (ugh).
Or Svelte and SolidJS which have brought massive improvements in performance and reducing JS with signals, compiler, etc.
Meanwhile MPA people are redefining the boundaries of work by marrying the frontend to the backend. They are doing some big re-architecture type stuff, and it is very interesting, far more interesting than React Query being the better Axios. If I had to lead with an argument about interesting changes on the SPA side, I would've lead with the ongoing improvements to CRDT libraries. It's niche but there really isn't much of a revolution going on otherwise on the SPA side.
Not sure what you mean by "fine".
There's nothing modern about client-side React. To get some perspective consider that more time has passed since today to the release of React in 2013 than from React to jQuery in 2007.
Oh my God! That just sent me into a mid life existential crisis for a moment.
The ROI proposition of MPA/hybrid becomes really meh.
Whatever the case, I think very few companies have reached the excellence of native macOS interface design in the context of a web app. Figma is a lone exception; for anyone else to achieve what they have, they'd have to reinvent the wheel yet again in so many small ways. (Have you noticed in Figma how moving the mouse down and to the right diagonally from a menu item to its associated submenu does not cause the menu item and submenu to be deselected? That detail, and so many others, are straight-up macOS-inspired UI craftsmanship.)
We need a reusable toolkit that lets ordinary developers achieve Figma-level UI excellence in web apps.
The amount of fiddling and tweaking required for web UI feels substantially higher than any GUI toolkit I’ve ever used. And I’ve used a lot of them!
I suspect this isn’t seen as a problem because Vite and friends do an amazing job of hot reload. But it is still a helluva brick wall to shipping things.
Please never let this happen.
Just think of all the functionality related to text that browsers give you in HTML: styles, spellchecking, selection, accessibility features, etc. And that's just text.
You lose any form of accessibility, inspectability, AdBlocking won't work, in many cases even mouse select/copy-paste won't work..
No need to learn html, css, JavaScript, bundlers, etc, etc.
No, it is not. Your criticism is very specific to React.
React is unbelievably overengineered, classic case of creating solutions to self-invented problems.
I once loved client-side frameworks like React.
Then I realized: Great, we managed to add complexity wherever possible. In the backend, in the front-end, in the DevOps stack, EVERYWHERE. And more layers will be introduced to keep all that distributed complexity in sync.
sigh
We can argue over the specifics for sure, but simply imperatively changing your UI whenever your data changes doesn't scale very far, neither in term of codebase nor in terms of team.
First, there is an implication that the HTTP model is benign in the complications that we see in web applications. I don't think it would take a lot of arguments to bust this? Trying to hide it, also leads to several problems of its own.
Second, that the rest of the abstractions in a browser are benign in the complications most people complain about. The DOM, CORS, general document structure, CSS(!), and all of the extra APIs that browsers have added through the years are building on some rather awkward layers. I don't think it is hard to argue that the biggest reason that browsers have had the success and development that they have had, is the privilege that we have given port 80 in the world.
Now. I think an area we would have solid agreement on, is that I don't necessarily think we had better options along the way?
Bringing this back to frameworks, though, tooling is tough to ignore. The tooling that people used to have in easy application creation is tough to scoff at. I think it is safe to say that Dreamweaver was also not that bad, looking back. We had some odd purity tests on whether or not it should use tables for layout. Hard to really keep that complaint top of mind when I look at the absurd amount of markup that is in so many sites, nowadays.
grid and flexbox are probably closer to actually being a one-stop easy-to-use paradigm with less nasty edge cases than tables, but all the table code stuff is still there if you really want to do it.
---
> I don't think it is hard to argue that the biggest reason that browsers have had the success and development that they have had, is the privilege that we have given port 80 in the world.
I actually think this is orthogonal. The power of frameworks like React is that nobody wants to write the same app five times (windows/mac/linux/ios/android) using sometimes wildly different native coding paradigms, and coordinating feature development across native platforms is like herding cats.
I mostly agree with the point that this is orthogonal to frameworks. I'm just putting that in here for why people disagree with many common web frameworks. A lot of the complaints that many of us have, are ultimately rooted in what they are building on top of. CSS, in particular, is remarkably ill suited for interface design.
People were doing things like making rounded buttons using tables, using things self-described as "clever hacks", and they mostly stopped working because as things like new viewport dimensions showed up you needed to paper over that too.
at least from what i've seen, the other strength of CSS is that it gets used for literally everything and so it's possible to build most conceivable layouts. A lot of the other layout frameworks either just use CSS, or you might run into edge cases because of the sheer amount of things in CSS that may not be well supported elsewhere or do not have a clear parallel.
But I don't want to belabor examples. Fitting everything to the DOM is probably a worse part of the problem. Especially with how people insist on trying to rube Goldberg the layout on the regular behavior, which is clearly for a much more linear document. (Incidentally, no complaints on it to represent a document...)
Then you try to make things stateless for the HTTP nature. As well as largely pretending that the URLs are file system paths.
Both of those land you with frameworks on the frontend that are easy to complain about. We then add to the pain by trying to use the same framework for native.
Sorry, I have been around the block so many times, there’s now a moat around the block.
Well it wasn’t just ReactJS, the whole JavaScript ecosystem went mad with its libraries and tooling for all these libraries but React was particularly annoying to get started so they built create react app so you can have a hello world app in a reasonable time.
The difference is, in SwiftUI you fire up Xcode and you are up and ready to build the thing you intend to. No tooling setup, no intermediate steps to transpile the code into something you can’t recognize and the “backend” that deals with the logic is the same language with the same paradigms. Mind you, SwiftUI is considered a downgrade when it comes to tooling. Yet everything fits and you didn’t spend mental energy to try to make the tools work as intended.
My mantra now is to use the tool that is built to do the things I want to do and stop trying to make make it work in ways it’s not intended to. That’s why when I want to have a web interface I simply work with DOM directly. That’s how the creators of the web browser intended:) No virtual DOM, no libraries doing magic and managing the DOM for me. I'm sure there's place for ReactJS too, it's just that its not for most use cases.
All I want is tools that I can fully fit in my working memory and don’t spend time trying to make things work so I can do the work I care about. Simplicity and robustness is the paramount.
I think the big difference right now is React has been released for 10 years vs SwiftUI's 5, so people had had the time to shoot themselves in the foot much more with React. IMO it doesn't take away from it still being much better than what it replaced.
> no intermediate steps to transpile the code
Sorry, but how is Xcode not "tooling"? And how is there no compilation step?
It should be obvious to us all that the frontend world needs more stable and reliable tooling. But pretending that native or mobile apps somehow don't need tooling is not a serious position.
> I simply work with DOM directly
Do you care to show us any apps that you've built with this approach?
So much of this debate is people talking past each other about what they need. Some people are building a glorified blog CMS, and jQuery is fine. Some people are building Figma, and think the former camp are insane for suggesting jQuery is fine.
> That’s how the creators of the web browser intended:)
The web is the best application delivery platform we currently have, so people will ship apps on it whether or not that's what Tim Berners-Lee thought they should be doing.
The overhead is so low compared to the web tech, it’s no comparison.
If you want to do something weird you can complicate things if you like but the defaults are great so most of the time you don’t have to.
You know how on web tech there's many tools like packers, linters etc? Those are all tools you need only because you want to pretend that JS is not JS and you end up putting a distance between yourself and the actual thing that runs so you loose your ability to understand what's actually going on because it's actually not your code that's running in the browser and you had to do the chores to achieve it.
On native development these things also exists(the CPU doesn't understand human readable code, right? However the abstraction layers are straightforward), the packer equivalent would be linker I guess(not exactly but...) but you don't have to even know about that unless you are doing something that explicitly requires you to control how modules need to be connected. These tools are mature and simple, they daisy chain, you don't go through huge configuration files and its usually just a flag you add when you want to do something non-default(which you wouldn't if you are doing something like building UI). For huge projects things can get quite complex but the complexity isn't the default, unlike React & similar.
Yeah that just isn't true. No matter how much you want it, the days of html pages with anchor tags and <table> elements centering content are gone.
Move on man.
It’s great.
Btw the web tech has come a long way since. Native browser API is amazing, CSS is wonderful and I’m particularly excited for Web assembly. Drop the virtual DOM stuff and all other Frankenstein BS and working on the browser is actually fun again.
I stopped hoping for the reason behind changing the class components API to hooks.
Did you? You can always opt for a simpler framework and you can avoid server orchestation. If you are not in the position to choose then you could work on starting your own project if you think you will have a efficiency edge over the rest with your simpler stack.
Sure you can centralize your complexity. But that doesn't necessarily get rid of this.
You can put database queries, business logic, UI interactions, etc all in one place.
ref as a prop: Refs can now be used as props, removing the need for forwardRef.
const error = await updateName(newName);
Why would updateName return an error? Why not just throw an Error like JS/TS?- People really like Result structures
- People who wrote the API believe in the "operational issues and business issues should not be comingled" philosophy (so this function might raise on a connection error, but it _won't_ raise when there's simply an error like a name conflict)
- People who wrote the example write Too Much(TM) Go
With enough front-end complexity, other state managers get in the way more than should. So, to anyone who might be tempted to hate on React, but really has just grown weary of endless walls of action constants, or plumbing props, or fighting nested providers/contexts, or resorting to pub-sub; give something like Jotai a shot.
https://github.com/pmndrs/zustand
https://github.com/pmndrs/valtio
To me it feels like Jotai has too much manual boilerplate and Valtio has a lot of proxy "magic" that while I do like it I don't feel like it would be a good idea for a team. Zustand sits right in the middle of boilerplate-vs-magic, and is what I chose for a large project we're doing now.
I ended up rolling my own solution [1] to escape all that so I could focus on getting things done. It's been working great for me in production. Too bad there's no popular option that works similarly.
For comparison, Valtio has the same kind of "counter" example at the top of their README (first and third code blocks): https://github.com/pmndrs/valtio?tab=readme-ov-file#wrap-you...
As a developer, I value solutions that never fail me. I wasn't driven to Jotai out of good taste. Simplicity and reliability are the benefits I find the most tangible. But Jotai's atomicity brings renderer optimizations as code splitting advantages that I haven't seen from the flux/redux clones before either.
I’ve used it in a largeish project and I liked it a lot.
I rally hope I never have to deal again with redux or sagas
Server Components also look fairly complex, and I'm glad I haven't had to deal with them so far.
The improved error messages on hydration errors are welcomed. The <Context> as a provider and ref as a prop changes are nice QoL changes.
Overall, I like React/Preact as far as building SPAs go. Using it with a feature-rich component library (say, MUI) and a simple state management solution (like Preact Signals) makes it very straightforward to build SPAs, as far as I'm concerned. But I worry about the complexity creep. The descriptions for the new hooks in those release notes put a massive cognitive load on me just by reading them.
The React Compiler, on the other hand, is a much needed tool. It should result in components that are less complex, as the programmer won't have to write typical optimizations by hand, as part of the component itself. I'm looking forward to its release and eventual integrations with Vite and etc. From what I heard, Preact will support it too.
I’d hate to have to deal with incompatible versions at the rate they release major versions.
If you try to stick with one version do you soon get stuck because you need to take a bug fix or security fix that’s only available in a later major release (but updating breaks other things)?
I want to build software on a stable platform so I can spend time on improving the software or writing something new, not keeping up with updates.
React is stable, upgrading it is painless as long as you don’t ignore deprecation warnings. What can be annoying is other (abandoned) dependencies holding you back from upgrading.
What's the solution?
Maybe if you have a small app. React is as bad as going from angular to angular 2
You have no idea what you are talking about.
15 to 16 - pain.
16 to 17 - pain.
If you disagree you haven’t worked on anything even slightly complex.
Thankfully I’m on my 2nd project of ripping react out for htmx. The last one was a huge success. No doubt this one will be too.
The original `createClass` API was indeed deprecated and removed all the way back in 2017 [0]. You can still use them today with the separated `create-react-class` package.
ES6 class components still work as-is even in React 19 - it's just the legacy context feature that's been removed. They're generally discouraged, in that function components are now the standard way to use React, but they're still not "deprecated" in the sense of a warning or removal.
[0] https://legacy.reactjs.org/blog/2017/09/26/react-v16.0.html#...
Regarding class components in general, what is the problem with maintainers choosing to encourage devs to use their new APIs while keeping the old APIs working?
- https://macwright.com/2024/01/03/miffed-about-react
(looks like the author may have an HN-specific redirect, so you might need to copy-paste that URL)
PS: I'm not a frontend engineer but I find this topic interesting.
Thanks!
The one real edge I'll give React is much better Typescript support due to tsx essentially being a superlanguage of TS. Vue's composables are very good, but it falls apart a bit in actual template usage. Tooling is also better, but that's also because it's simply used much more so has had more investment into making the tooling good compared to Volar for Vue.
But in my opinion everything else surrounding Vue makes it superior. Signals are a better state management pattern, there aren't all the insane footguns that React comes with, performance is better out-of-the-box and is practically impossible to fuck up compared to React where it's hilariously easy to make even the simplest of apps be performance monstrosities, the documentation is (IMO, I find React's docs (yes I've seen the new ones) terrible) best-in-class, the gilded libraries like Pinia, Vue Router, VueUse are far superior to anything in the React ecosystem...
I could keep going, but having worked with both more or less equally, I'd choose Vue 10/10 times over React, no questions asked. I can throw a junior at the codebase and be 100% confident they'll make something that's more-or-less idiomatic Vue code, even with the Composition API which is less stringent than the old Options API, whereas with React they'll always need hand holding and I'll always need to explain why things are rerendering twice or running terribly or what useMemo does or what useEffect does (or doesn't) do...
Today, 33% of vue downloads in the last 7 days are for vue 2.
There was a lot of things that were nice in the vue world like vite and vuex, but I'd never recommend vue to anyone, especially anyone that wants a good typescript experience.
here's an example library button using .tsx in vue https://github.com/vuetifyjs/vuetify/blob/master/packages/vu...
Pinia is Vuex, it was made by the same people specifically for Vue 3 due to otherwise having to introduce a lot of breaking changes and is a lot simpler than VueX was, as it leverages the composable pattern and gets rid of the need to do things like `mapGetters`/`mapActions`. And VueX 4 is still an option for those that prefer that approach.
> ... class mixins
Those were a pain point, but no longer relevant in Vue 3 as mixins have been deprecated. Again, composition takes its place and is in general much more powerful while being simpler. For a great example of what composables can achieve, I'd recommend taking a look at VueUse (https://vueuse.org/)
> Today, 33% of vue downloads in the last 7 days are for vue 2.
Another way to look at that is that the majority of the community is on Vue 3 :)
> If you want to use vue with a .tsx file you might as well use react.
`.tsx` is very much a personal preference thing and isn't really considered idiomatic despite Vue having support for it (unless you're a library author like Vuetify that you linked). I personally can't stand working with `jsx` and find Vue SFC's superior, and again, typechecking these days is much better than it ever was and will work just fine in 95% of situations. Especially with things like component generics being introduced, it's only gotten better and actively getting better.
I'd highly recommend you give Vue 3 a try with an open mind, because things have only gotten more powerful while getting simpler since the Vue 2 days.
I have the exact opposite experience, I find Vue hilariously bad to the point of being repulsive. Now what?
It's harder to do poorly and even when you do, it doesn't punish you the same way that React does.
Native development is definitely a pain point, unfortunately there's few options other than React Native there. Problem being that React is backed by Meta, so obviously it has a lot more money being thrown at it compared to competitors like Vue or Svelte.
There are certainly more UI libraries available for React than any other framework [1]. But do you think that these are also clearly better? What would be your go to framework for React? To me, it seems that the trend is going to framework-agnostic or multi-framework libraries anyway (e.g. Ark UI or Zag).
But gun to my head, Shadcn would probably be my choice. For Vue it'd be PrimeVue. Those are the two highest quality ones I've tried in small projects, so no clue how they scale in real-world projects.
That's doing a *lot* of heavy lifting here. That's like saying "D is infinitely better than C++, except for available libraries".
While my current Electron personal project will probably use Vue because I want to learn it, the change in libraries (and lack of plug-and-play support for whole companies' provided frameworks) is a real barrier to entry for a lot of work.
There are millions of developers happily using react every day. They just don't come onto HN to complain about the "woeful state" of frontend.
If building a SPA site with vite use tanstack/react-query and react context. There are other great libraries like zustand and jotai that can make sense in certain kinds of more complex applications.
const [name, setName] = useState('blastonico')
...
setName('nailer')
You do: let name = 'blastonico'
...
name = 'nailer'
Also a single .svelte file includes everything you need for a component (HTML, JS, CSS), so it's easier to manage.I get that assigning variables is easier to understand, but it's way, way harder to actually scale and maintain. Check out flux architecture.
We’re not just assigning variables directly, current JavaScript frameworks use a compiler.
const [state, setState] = useState(0)
const func = () => {
console.log(state) // 0
setState(40)
console.log(state) // 0
}
[foo, setFoo] = useState(1);
[bar, setBar] = useState();
setFoo(10);
setBar(foo * 2); // Is bar 2 or 20 at this point?
Let's say you instead did the `setFoo` and `setBar` in a click handler. In that case, when you click the button it would tell React "Hey, in the next render set `foo = 10` and `bar = 2` (since `foo = 1)`. Then React goes ahead and runs your function again, and `foo` and `bar` will both be updated.
The value of `foo` does not change within a render cycle, you literally don't have to worry about state.
It might seem that there’s a chance that people will be confused about what bar is, but in practice all the changes are happening in handlers and bar will be a const anyway so you have no plans to mutate it directly.
Just a follow up. If foo and bar are expected to be constant in the rendering code, what's the point of the setXXX() functions? Why not just make them constant explicitly and say mutating them elsewhere like in the handlers/controllers?
React inverts the MVC paradigm and says "no, you don't get to decide when to render." So if you want to update state, React will manage that for you and queue up the render. With React, your UI and state literally cannot go out of sync (except for refs), and all the data dependencies are managed for you.
Facebook gave a great talk on Flux architecture vs MVC ten years ago that you should check out here: https://www.youtube.com/watch?v=nYkdrAPrdcw
> what's the point of the setXXX() functions? Why not just make them constant explicitly
Look at the code again: it is explicitly constant! `const [myState, setMyState] = useState(0)`. `myState` is a const, and will literally not change its value for the entire render cycle. There is no mutable state to manage, no race conditions. You just tell React what to render based on what the value is now, and React injects the current value for you. The first time, `myState` is 0 since that's the initial value. Every subsequent render, React will give you the latest value. You can pretend everything is constant, because it is.
First of all, I don't believe React component is pure functional with the state hooks embedded inside the component with side effects. Calling UI=F(props) twice with the same props would not produce the same result given the different sets of states embedded in them.
Second, the local variable myState is const but the state is mutable; the variable myState is an alias snapshot of the state. Otherwise what's the purpose of handing out setMyState? setMyState is for mutating the state, right? It seems the need to keep myState constant is due to React's inability to detect changes to the variable to sync up the UI. It uses setXXX() to trigger the UI re-rendering. However, whether setXXX() queuing up re-rendering and causing re-rending loop is inconsequential to the programmers. It's React's implementation detail.
Third, I'm interesting in learning what kind of bugs mutable state would cause in React, so that we can design better systems down the road.
Correct, but you as the component writer don't care. From your perspective, you are writing a purely functional component because you have no control over the injected state. So your function is "pure" with respect to the props that are passed in and the state that is injected by React. It's actually UI = F(props, state)
React can (and will) run your component function multiple times with different values before rendering, so it is extremely important that you have no actual side effects. Otherwise, these "intermediate renders" will affect the final render, which breaks the contract that your function return the same values for the same inputs.
> the local variable myState is const but the state is mutable
It is "mutable" in the sense that it changes between invocations of your function. But no, it is immutable within a single render of your function. The fact that you can treat all state as constant is one of the massive advantages of using React. You literally don't have to think about state mutating within a render cycle. You just write a function that spits out JSX given props and state.
> Third, I'm interesting in learning what kind of bugs mutable state would cause in React
You're going to run into issues where:
* the order that your function is called somehow affects the final render. Now you need to worry about how your function is called, and with what values. Not an issue with React.
* the underlying state is out of sync with the UI, because you changed it but didn't trigger a re-render. Not possible in React (except for refs).
* the internal state of the component ends up in an invalid state because of the ordering of set-state calls and renders. Again, not possible in React because all set-states are batched together and applied consistently to the next render cycle. There's no such thing as a "partial render".
This is like calling the constructor of an OO class a pure function. The class constructor takes in parameters (props) and the created instances don't interfere with each other's states. With all due respect, this stretching of the definition of pure function is beyond recognition.
> * the order that your function is called somehow affects the final render. Now you need to worry about how your function is called, and with what values. Not an issue with React.
The order of the function invocations calling setXX() matters anyway in React or non-React libraries. The queued up setXX() calls pending state updates in React has an order. There's no difference in handling state update ordering between React and others.
> * the underlying state is out of sync with the UI, because you changed it but didn't trigger a re-render. Not possible in React (except for refs).
> * the internal state of the component ends up in an invalid state because of the ordering of set-state calls and renders. Again, not possible in React because all set-states are batched together and applied consistently to the next render cycle. There's no such thing as a "partial render".
Both of these are because React's inability to detect changes to state updates in a comprehensive and fine grained way.
No, because again I must stress that you cannot control the injected state. You merely ask React to set state in the next render. The next call to your function may not have the new state! React can and will call your component function multiple times with different values of state, so you must assume it could be anything. This is why component functions must be written without any side effects, because there is no way for you to know which invocation React will actually persist to the DOM. For this reason, you really are writing a pure function with respect to props and state. It's a requirement in React!
> There's no difference in handling state update ordering between React and others.
The huge difference is that because state is fixed within a render cycle, it is not possible to read an intermediate value. You can't get in a situation where one handler updates a state value, and another (or the same) handler reads that new value within the same render cycle. That's the sort of order-dependent nonsense that can make a component very buggy and fall into an inconsistent state.
> Both of these are because React's inability to detect changes to state updates in a comprehensive and fine grained way.
That's because React is built in a way to provide a set of very specific guarantees when it comes to managing state and rendering it. You are free to come up with "simpler" solutions, but you are going to have to sacrifice some of these guarantees for that simplicity. React component functions have no side effects, and are defined completely declaratively. That is extremely powerful with a lot of advantages, such as being trivially composable. It is extremely easy to extract functionality out of a component and turn it into a reusable hook, because everything is already stateless.
If you ditch all that just so you can use variables, you lose all of those benefits. You'll have to deal with truly stateful components, ones that are path dependent and difficult to reproduce for debugging. By contrast, you can reproduce any React component's UI by passing in the same props and state. This is only possible because state is external to the component and out of your control.
With all due respect,
> For this reason, you really are writing a pure function with respect to props and state.
A pure function by definition is one which returns the same output for the same input. The output (html) of the React functional component with the same props can be different based on the changed state. It is not a pure function. It's really no different from an OO object with internal state.
> There's no difference in handling state update ordering between React and others.
> > it is not possible to read an intermediate value.
There is no intermediate value. All value changes are in the final form as there is no multi-threads reading and mutating the state. The block of code mutating the value is executed fully before another block of code can read it.
As for multiple handlers reading and rendering the state and some might miss the change by another handler, again it's a problem of React's inability to detect change for each handler. If every handler can detect change by any other code (other handlers included), there's no problem.
> That's because React is built in a way to provide a set of very specific guarantees when it comes to managing state and rendering it.
React requires that set of guarantees because its design decision - its use of diff to detect changes. It's a non-issue in other frameworks and solutions.
Yes, and the input includes state. React manages it and sets it before your function runs; your function then reads those values when it calls the hooks, and it is read-only. If I adjusted the React syntax to pass in state as a function argument instead, wouldn't you agree that it is pure? It's the same! Just because it's not passed in via arguments does not mean it is not an input. And a pure function is still pure even if the caller is stateful.
Consider the "rules of hooks" in React: you cannot conditionally use a hook, and hooks must be used in the same order every time. That's exactly the same as regular arguments, making them functionally identical but with better dev ergonomics. That's on purpose: state is an input, but having it passed via function arguments would suck to use.
Question: have you written any React components? This is a basic rule that is one of the first things you learn: components should be pure functions with respect to props and state. They're not even allowed to set state as a side-effect. If you're still convinced it's not pure, can you tell me how a component function's output can change given the same props and state?
> The block of code mutating the value is executed fully before another block of code can read it.
And that's the problem: with arbitrary code, there is no such thing as a distinct "block of code". One function can read value A, set it to B, then call another function, which sees value B, does something as a result, and then it renders. But that's wrong: value B has not been persisted to the DOM yet, so it should not have been read by the second function. Now you're in trouble, because your component is behaving as if both A and B are true at the same time.
This is not possible with React. But to pull that off, they had to externalize state and make it read-only to your component.
This is the same argument that the member variables of an OO object are additional input to its member method and the method is "pure."
> how a component function's output can change given the same props and state?
This is the same argument that given the same values of the member variables of an OO object and the same method arguments to its member method, the method returns the same value.
All these are just twisting the meaning of words and concepts to fit the square React into a functional round hole.
> a basic rule that is one of the first things you learn: components should be pure functions with respect to props and state.
You can certainly mutate the state in a React component; otherwise, what's the purpose of [.., setXX] = useState()? If such a "rule" is so important, why don't React remove the ability?
BTW, the "rules of hooks" are another set of extra burdens. All these rules imposed on the programmers are there due to React's weak design.
> And that's the problem: with arbitrary code, there is no such thing as a distinct "block of code". One function can read value A, set it to B, then call another function, which sees value B, does something as a result, and then it renders. But that's wrong: value B has not been persisted to the DOM yet, so it should not have been read by the second function. Now you're in trouble, because your component is behaving as if both A and B are true at the same time.
If every renderer can detect every single update of a variable/state, the above is a non-issue. Function1 can set v1 to A. The renderer detects the change to v1 and renders it as A. Function2 set v1 to B; the renderer detects it and renders it to B. Function1 and Function2 can be called in any order; the rendering output is consistent with the state. The renderer might be called twice but who cares the eventual outcome is the same (certainly there're memorizing optimization to avoid re-rendering). It's really React's weak design causing all the out-of-sync rendering problems.
So there will be 3 cycles?
1: foo = 1, next(foo = 10)
bar = undef, next(bar = 2)
2: foo = 10
bar = 2, next(bar = 20)
3: foo = 10
bar = 20
Does the above sound right?It just feels a bit weird that there's special .svelte specific rules.
Runes kinda fix this, but it's still a bit weird.
I think Solid or Vue are much simpler (but only did small projects in them) and have a simpler mental model. I've not yet used Preact, but heard good things about it
1. Write some solution with out a UI
2. Decide you want a UI
3. Add React
4. Be forced to re-architect your solution because react wants control of all of your state.
React is supposed to be the V (View) in MVC but it requires full control of the M (model) in MVC and bleeds into the C (controller) as well.
Someone will likely chime in that you can just tell React to re-render the entire UI every frame or write lots of custom functions to monitor your model but that's not really the point. No other UI paradigm requires this.
- design "UI struct" for what you want to display
- Have React fire off events when doing actions
- Those actions get piped into your UI-less solution
- Your UI-less solution updates the "UI struct"
- React updates the parts of the tree that was using part of your struct
if you design this struct in the right way, you can have the updates be _very_ targetted (like, React doing basically no extra work). But your UI struct needs to be really carefully set up so you're not firing things off all over the place.
I think it's still an easier problem than keeping your DOM in sync entirely, but it's unfortunately very easy to accidentally over-render still.
Are you referring to Electron apps or something?
What aspects of Django do you think still stand out compared to Phoenix? It seems like a very solid framework, specially with the recent release of Phoenix LiveView 1.0, which seems like a pretty solid approach to frontend. For context, I’ve worked with Django before but didn’t particularly enjoy the experience—not because of the framework itself (its documentation, ORM, and admin tooling are excellent) but because I’m not a fan of Python, particularly its packaging ecosystem and approach to async, which I find lacking. I haven’t used Phoenix or Elixir before, so I’m curious to hear from someone who has experience with both.
Take ORM for example. You write a model and you get out of the box:
- migrations to create the model and to apply schema changes; - form validation for crud; - admin with permissions to edit it; - helpers to get model by id or throw 404.
Phoenix kinda is in the same market, but you write your migrations yourself, admin panel is a package somebody slapped on top, etc.
It’s not that Phoenix isn’t usable, but getting on that level takes time and effort
It uses a 500-line router and a 500-line UI component lib.
However, I'm disappointed (but not surprised, this was listed as out of scope for 19) that triggering Suspense is still basically "use a framework that supports it." I have not been able to find any documentation or blog posts about the mechanism. I've tried to figure out how it works by looking at TanStack Query, but I've had limited success so far. I've found they're copying React's twist on Promises [1], but I haven't gotten this to work yet.
I know the general idea is you throw Promises, but Suspense explicitly forbids using promises created during rendering. This means you can't just interrupt the component's initial render to load some data, and then restart it when its data is available. This means the component needs to deal with null data somehow, instead of, e.g., being able to call a custom `useSomeData` hook and rely on it to first suspend and then return the loaded data. Not having to deal directly with loading states in individual components could simplify things quite a bit.
Has anyone explored this side of Suspense?
[1]: https://github.com/TanStack/query/blob/main/packages/query-c...
- https://bsky.app/profile/acemarke.dev/post/3lcitbmmfss2i
Big picture as I understand it:
The legacy and always-undocumented-but-everyone-knew-about-it approach was throwing a promise while rendering.
`use` still actually does the same thing, but it also attaches some extra status fields to that promise, _and_ checks to see if you're consistently passing in the _same_ promise reference.
In other words, it's the job of an external data fetching library to keep track of what query entry is being asked for, create and save a promise per cache entry _outside_ of the React component tree, and then return that promise somehow so the app developer can pass it to the `use` hook. In a sense, it's an async `Map`.
As another example of this, my former teammate Brian Vaughn (previously on the React core team) ended up building his own implementation of that behavior in the conveniently-named `suspense` package:
- https://suspense.vercel.app/
Ultimately, the `use` hook and Suspense _does_ do exactly what you're asking for - the rest of the component gets to assume the data _does_ exist, since `use` will only let the execution continue once the promise has resolved.
If you're going to add something to the main project, it should be well-designed, clear, and in good taste. React won over things like Angular because the latter had poorly designed abstractions. It was supposed to be "just javascript" (which was always more of a vibe being actually true).
Just look at wtf actions are. In their blogpost[0], the old way of doing things is only a few lines more, but is much clearer. The 'useTransition' still has to update the error state - but at least it saves you from typing the pending state!
But of course, you're not supposed to use this directly, you're supposed to use useActionState. And this blog post makes it's usage very clear by just returning null to show something that's supposed to update state. So very clear, and intuitive /s
Stuff like this really should've been in a separate library. It baffles my mind that core behavior like state management is left to external solutions, but then random crap like this makes it into the main project.
A description fit for React itself.