> React was meant to be a way to provide snappy page loads and UX.
This is a very common misconception. React was meant to provide one-way data flow. With an app built directly on the DOM you have to deal with the DOM having its own state to manage on top of the state your own code is storing. You have a list of comments in a variable, and a list of DOM elements for each comment, and nothing but your own code is making sure they stay in sync with each other. React changed things so that the state of the DOM is always derived from your own app's state, which eliminates what turned out to be a pretty tedious and error-prone amount of work in complex web apps.
It wasn't the first to provide this but its API was unique and compelling vs existing alternatives. The virtual DOM, server-side rendering, etc. are not things that make React faster than non-React code, they are things that counteract the inherent slowness in React's design to make it competitive with non-React code.
Watch the original JSConf talk where React was publicly announced and released, and notice how the talk is mostly about the one-way data binding, and the virtual DOM/reconciliation are mentioned in the back half as ways React catches up to non-React app speeds: https://www.youtube.com/watch?v=GW0rj4sNH2w
Not really a misconception: it was explicitly pushed and advertised as such, most of the advocacy (especially from React fans) at the time React was introduced and started gaining traction was about the virtual DOM being "faster".
>React changed things so that the state of the DOM is always derived from your own app's state, which eliminates what turned out to be a pretty tedious and error-prone amount of work in complex web apps.
I dunno, I used Redux for a few years, and it was a "pretty tedious and error-prone amount of work in complex web apps" too.
Controversial opinion: Redux (and the Elm architecture behind it) only works with a typed language like TypeScript (or Elm) which takes away the error-prone part. With good type completion, some of the "pretty tedious" part goes away as well.
You're probably right about Elm which is basically one big reducer, but Redux adds a whole lot more indirection on top of that which makes it much more complicated.
Even small Redux apps can start off with a lot of indirection as soon as they extract logic into selectors. This is probably the first area where Redux becomes more complex that what you were doing before:
It reminds me of reading a bunch of parser combinators: it feels like you're reading code that builds something that does what you want instead of the code that just does what you want.
If you use TypeScript and Thunk, it’s no more work than writing your own state management code on plain JS/TS objects. But you get all the advantages of Redux (dev tools, introspection, replayability, easy persistence and tab sync, etc).
Yeah strong typing is essential. Redux is overkill for small or even medium apps but it's the best tool I've found for dealing with the complexity of larger apps. Having a very clear, inspectable sequence of mutations to all your data becomes very valuable.
No. My team migrated to react from in 2015 because the biggest selling point was maintainability, not speed. The virtual DOM was originally marketed as why “react is NOT slow”. It was never about pure speed. I think the misconception all came later by other people.
I'm sure React fans who misunderstood the virtual DOM (which was explicitly advertised because it was the most popular part of React[1] vs the other parts that people were more critical of) may have said this, but I never saw the project itself advertising itself as faster than vanilla JS, only that it could be faster than competing frameworks, _especially_ ones that rebuilt the DOM unnecessarily.
> I dunno, I used Redux for a few years
Redux is a different library than React. State management across an app is a problem even for non-React applications, it's not like React _uniquely requires_ work to address state management.
I don't see why your dissatisfaction with Redux has anything to do with React making a very specific and buggy part of building web apps easier to manage in return for a performance cost and following its API.
Here’s @vjeux: “React is a JavaScript library for building user interfaces developed by Facebook. It has been designed from the ground up with performance in mind.”
If you worked on the web a decade ago, this stuff was everywhere and because Facebook was at its peak there was this bizarre reality-denial effect where people would have an app which was slow, soaked memory like a sponge, and they’d insist that was as good as it could be because Facebook and Instagram were using the same framework. Reality intruded enough eventually that people started talking more about things like developer experience but you can still find people arguing that needing 4MB of JavaScript for a contact form is normal.
None of those links say that React is faster than using no framework, just that it is fast, presumably compared to other frameworks or techniques before that did DOM replacement.
I guess you could say that not being specific was misleading but we'd have to agree to disagree on that. I _did_ work on the web a decade ago and my recollection is that it wasn't ever unclear that React's performance claims were that it was fast for a framework and not faster than equivalent manual DOM mutations.
> I _did_ work on the web a decade ago and my recollection is that it wasn't ever unclear that React's performance claims were that it was fast for a framework and not faster than equivalent manual DOM mutations.
That was a very common claim - if you search for old comments there was some very magical thinking about virtual DOMs at the time. I do agree it was worse in the fanboy circles - there’s a game of telephone where nuance is lost at every iteration so you’d sometimes have a blog post where someone said they saw a big win replacing a thicket of jQuery plugins and it’d eventually be repeated as “React is ZOMG FAST!!!!” with a few people trying in vain to suggest that replacing a bunch of organic code with something planned probably mattered more.
Anyway, my point isn’t that React is terrible but more that you really want to measure & review assumptions to make sure you’re not relying on something stale. It’s still easy to find assumptions from the IE6 era shaping what people think of as fast or slow, and especially with the massive front end framework trend it’s easy for people to have enough layers that their understanding of their application’s performance is far off. Choosing React is fine, just make the trade offs deliberately.
I do vaguely remember the Virtual dom was being advertised as faster. E.g. minimizing of updates by evaluating the dom-tree and e.g. moving entire branches. I dont think it was devs misreading intent here, maybe just in hindsight that dom-manipulation wasnt all that important of a bottleneck
> I dunno, I used Redux for a few years, and it was a "pretty tedious and error-prone amount of work in complex web apps" too.
This makes no sense. Redux is extremely simple with a very small API. If the code using it is tedious and error-prone, that's the fault of the people who wrote that code not Redux.
E.g. "everything must be an action and have an associated reducer" is nothing to do with Redux itself.
We're at the point where many newer engineers haven't had real hands-on DOM experience but are expected to deliver applications built in React. You need to know at least one level abstraction below your current one to use the tool effectively. This all tracks with how the industry's changed, how we hire, how we train, and so on.
> You need to know at least one level abstraction below your current one to use the tool effectively.
I'm not sure that's true in general.
For example, for some tools there's no single 'one level abstraction below'. Let's take regular expressions as a simple example. You can use them effectively, no matter whether your regular expression matcher uses NFAs or Brzozowski derivatives under the hood as the 'one level [of] abstraction below'.
(Just be careful, if your regular expression matcher uses backtracking, you might get pathological behaviour. Though memoisation makes that less likely to hit by accident in practice.)
>For example, for some tools there's no single 'one level abstraction below'. Let's take regular expressions as a simple example. You can use them effectively, no matter whether your regular expression matcher uses NFAs or Brzozowski derivatives under the hood as the 'one level [of] abstraction below'.
But you do need to understand the abstraction of strings, code points and so on, if you want to do regexes on unicode that doesn't stop at the ASCII level.
In general yes: it's not an absolute law that you need to "know one layer below". You can code in Python and never know about machine code.
But knowing the layers below sure does help making better decisions if you want e.g. to optimize this Python code. Knowing how the code will be executed, memory layouts, how computers work, access latencies of memory, disk, network, etc sure does help.
I already addressed that in my original comment. Approaches based NFAs and Brzozowski derivatives don't have these flaws; but you don't need to know anything about how they work to use them.
You just need to read one blog post that tells you to avoid regular expression matchers that use backtracking, and you are good to go. You don't even need to understand why matching via backtracking is bad.
> But you do need to understand the abstraction of strings, code points and so on, if you want to do regexes on unicode that doesn't stop at the ASCII level.
>You just need to read one blog post that tells you to avoid regular expression matchers that use backtracking, and you are good to go. You don't even need to understand why matching via backtracking is bad.
Yeah, no.
You might not be able to avoid using your standard lib's regex, or your project's chosen regex dependency - based on team/company policy. So it's not as simple as "use a regex engine that doesn't has this flaw".
Then if you want to avoid the cost, you need to know what backtracking is, to the level of understanding which kind of expressions can give you those performance issues.
>Why?
Because there are tons of factors that can affect your regex experience with unicode, normalization, different lower/upper case treatment, composite characters that don't match even though it looks like you typed the same character in your query, handling new unicode characters (ASCII 7/8 bit has been fixed for decades) and so on.
> You might not be able to avoid using your standard lib's regex, or your project's chosen regex dependency - based on team/company policy. So it's not as simple as "use a regex engine that doesn't has this flaw".
Well, yes, if someone forces you to use tools that have flaws, you need to learn about the flaws so you can work around them. Like when using a shoe as a hammer.
I'm not sure that proves anything about abstractions?
> Because there are tons of factors that can affect your regex experience with unicode, normalization, different lower/upper case treatment, composite characters that don't match even though it looks like you typed the same character in your query, handling new unicode characters (ASCII 7/8 bit has been fixed for decades) and so on.
> (Just be careful, if your regular expression matcher uses backtracking, you might get pathological behaviour. Though memoisation makes that less likely to hit by accident in practice.)
Doesn’t that exactly demonstrate why using the tool effectively requires an understanding of the implementation (or possible implementations) behind the abstraction?
Understanding is perhaps sufficient, but not necessary.
You can just consult a list that tells you which regular expression matchers to avoid (like eg Perl), and which ones are good (like grep), and you are good to go. No need to understand anything.
It does. Their argument is a farce. By now they've had many chances and made many attempts to illustrate their point if they had one. They don't have one, but they somehow don't know it. What can ya do?
Understanding is perhaps sufficient, but not necessary.
You can just consult a list that tells you which regular expression matchers to avoid (like eg Perl), and which ones are good (like grep), and you are good to go. No need to understand anything.
Regular expressions are probably not a good example because you will eventually write a regex that has catastrophic backtracking behavior. I encountered one a few months ago, so it’s not at all uncommon or difficult to encounter. If you’re curious enough, you’d end up reading about how regexes work under the hood.
A better example might be that of a compiler, where you (very rarely) need to look at the asm output or encounter a case where the compiler generates incorrect code and you need to debug why.
> Regular expressions are probably not a good example because you will eventually write a regex that has catastrophic backtracking behavior.
Nope, that will never happen to me. No regular expression has that behaviour.
There are some bad implementations of regular expression matching that have these problems for some regular expressions. But you can avoid those bad implementations without understanding anything.
> I encountered one a few months ago, so it’s not at all uncommon or difficult to encounter.
That only happens, if you use a regular expression matcher that uses backtracking. Sane regular expression matchers take linear time on all input strings.
> If you’re curious enough, you’d end up reading about how regexes work under the hood.
There's no one single way regular expressions work under the hood. You had the misfortune of using a matcher that uses backtracking and is prone to catastrophic exponential runtimes.
There's multiple different ways to implement regular expression matchers. But a user doesn't have to care or understand anything (they just need to avoid the buggy ones).
Sure, if you read up on how regular expressions work under the hood, you can learn to avoid those bad matchers. (Or you can learn how to live with your batch implementation, if you are feeling masochistic.)
But that's entirely optional: You only need to read one blog post that tells you to use grep and avoid eg Perl. You don't need to understand why backtracking is bad for regular expression matching; as long as you avoid those bad matchers.
I would say that knowing that there are such things as different families of regex compiler, what their internal methodologies and consequences are, so that you can avoid certain otherwise non-obvious problems that arise not from something you did wrong, but something a layer lower did wrong (you wrote a valid regex according to all the rules in the manual, and got a bad result) qualifies exactly as an example of needing to have some understanding of how the layers below work.
In fact it wasn't necessary for me to qualify that with "I would say". I do say, and it simply does. You've made exactly no argument this entire thread.
Maybe everyone doesn't need to know everything, but the skin of stuff anyone needs to know is thicker than 0, and has no absolute boundary layer either, you just generally need to know less the further from your own work. But that never goes all the way to 0. You have to rely on other people to have done their jobs, but you still at least have to understand what those jobs are, that they exist and how you ultimately interact with them and how they impact you.
You said so yourself several times which makes this all farcical.
I’m not sure if this response was simply for the sake of replying, with the claims of writing perfect code all the time or how backtracking implementation is uncommon or insane (most languages use backtracking implementations of regexes).
Huh? I'm not making any claims of writing perfect code. If you have a sane regular expression matcher, there are no catastrophic cases to avoid.
Regular expression libraries that don't use backtracking are available for many languages. Yes, some languages have bad libraries that use backtracking, too. But bad libraries will always exist, they aren't an excuse when there are more good libraries around then ever before.
You have a point, but it seems clear to me that your parent commenter was referring to more pervasive abstractions like frameworks and probably programming languages.
Unless you're coding in Perl or sed or whatever then regular expressions arent really a primary abstraction. And even when they are, I don't see how the implementation wouldn be accessible as a lower level. They're not really a layered abstraction.
I am saying that regular expressions are an abstraction that has many different implementations. So there's no single underlying implementation you need to understand.
The only thing you need to watch out for is regular expression matchers that are prone to exponential blowup. But you don't need to understand anything; you can just consult a list of which ones are bad and which ones are good, and then avoid the bad ones; without any understanding of the mechanics necessary.
> You have a point, but it seems clear to me that your parent commenter was referring to more pervasive abstractions like frameworks and probably programming languages.
Probably. I was just looking for the simplest example that the maximum number of people would be familiar with.
People start using React as part of a larger framework or existing app and they associate all these unrelated things to React.
Also, the poster says this line:
> Finding a dev who actually groks the gap between useEffect and useMemo, error boundaries, hook based fetching or my (un)favourite, authentication, is difficult.
But truthfully the problems those constructs solve are problems in every paradigm. If you can’t grasp the difference these things despite being a heavy user of a library, you may… want to spend some time reading the docs at some point.
Unfortunately all the early was advocacy focused on how the virtual DOM is "faster", so the people are fully excused for not finding out "what it was meant for".
The "UI as a function of state" was not just sold as "more functional/simpler", but also as a necessity to have a DOM diffing algorithm to minimize updates and be "faster".
I dont use react professionally(vanilla) but its ideas of one way data binding and UI is a function of state have continuously been helpful in building predictable apps that doesnt grow too hairy. an app can still grow in complexity as it becomes bigger but the ideas definitely help
Yeah, I cannot count how many times I've seen it claimed that the virtual DOM is the secret to why React(or another framework) is fast, completely missing the point of the virtual DOM.
The virtual DOM is not faster than performing direct mutations of the actual DOM, the virtual DOM is a tool that allows the normally slow approach of "blow away and rebuild the world" to be fast enough to put into use.
Virtual DOM used to be faster than DOM. DOM operations were really slow back when React came out, and the usual componentization approach of replacing entire blocks of code with new HTML strings used to lock up the browser. React made it possible to effortlessly reuse previous state DOM nodes.
Your second statement that the virtual DOM lets you skip unnecessary DOM mutations is true, but the first statement is inaccurate because "DOM" is not equivalent to "regenerate and replace all the DOM nodes with updated ones".
Prior to React, performant apps that weren't using frameworks that regenerated the entire DOM tree would simply manually mutate the DOM nodes based on what it was doing. If your app was loading a new comment, it would find the list of comment nodes and append a new one to it, same as a virtual DOM would.
The problem is that this could be error-prone in large apps—are you even sure that the comment list is still on the page? If it's not, do you need to add it to the page or is this a completely new view and you're reacting to a network request that finished after the user navigated away from the page? That's the kind of finnicky manual work that React helped simplify, but the performance was the same as an app manually mutating the DOM plus the extra virtual DOM comparisons.
The usual approach used to be to simply replace entire "component" with updated HTML string returned by a function representing that component. Doing what you're saying was not feasible for large apps, that led to unmaintanable spaghetti code and never really worked correctly - imagine you need to add a feature somewhere and then you have to go into all the other components that rely on that internal structure. I am talking about CRMs and other business apps like that, not some light JS to load blog comments.
None of what you’re saying is globally true. It might have been true of the apps you personally worked on but it’s not the case that everyone did HTML string replacement or that using the DOM directly forced you to forget basic software engineering concepts.
It's what was commonly done across more than 10 companies in Europe over a decade I worked in the field. Looking back at the source code of projects back then, it was the normal method.
The thing which was slow is changing more than you need to change. When the React marketing push included performance, that’s almost always what they were comparing it to - someone would have slow code making the same updates multiple times or triggering reflows by forcing the browser to do a partial update to measure something, and then updating again.
There’s an argument that the guaranteed overhead of using React is better because it helps the average developer who doesn’t measure performance much do a better job than they might have otherwise, and that can be true for many people but it also tended to get oversimplified to “React is fast” despite widespread evidence to the contrary.
We measured performance, but we also measured things like how hard it is to implement a feature or how many bugs we have to fix, and how quickly we can do so. When we jumped on React in 2013, it improved all of these metrics.
You're right that it was difficult, that's part of why React caught on. But lots of apps did it anyway—its not as impossible as you make it seem if you take the time to write some abstractions around checking what needs to be done or centralizing all DOM operations to reduce the chance of other code modifying then. I worked on multiple complex web apps that did things like this. It's just tedious and error-prone.
That's my whole point, though - it was tedious and error prone, so it wasn't usually done. Then React offered an easier and more performance way, that's why everybody jumped on it.
If your actual point is that "The virtual DOM is faster than a slow-but-common pattern of DOM mutation" then, sure. We have different experiences in how common wiping out the entire DOM really was in apps not using frameworks but differing experiences is normal.
But in a comment thread of people saying the virtual DOM is not faster than equivalent manual DOM mutations you can understand why "The virtual DOM was faster than the DOM" got understood differently since it lacked that clarification.
Well that's what React originally compared against. Sure, you could do it the manual, tedious and error-prone way to achieve similar performance, but that's not really interesting to React users.
Nope. The binding is "one-way" in the sense that, when the component state (or props) change, the DOM is updated, but if the DOM changes, the component is not updated. Hooks are a pattern for declaring state, side effects, etc. but they don't materially change this relationship.
> React is the automatic target for a lot of newbies. They jump straight into webdev, learn some HTML/CSS and eventually work their way towards React for employability.
This has been the trend largely for last 3 to 4 years with the candidates (<5 yoe) I have interviewed. I probe them on core fundamentals of Javascript, HTML and CSS. When I get to the nuances, most of them outright call it out saying that they are React developers and do not do Javascript without realizing the fact that React is based on Javascript. And other common misconception is that they assume JSX works the same way while writing the vanilla Javascript code.
Yup. I’m hiring for a mid-level FE role right now, and the number of “React developers” that don’t know JS fundamentals is incomprehensible. I’m not talking about anything esoteric. Just the sorts of things that I as someone that’s far from a JS expert considers necessary to work in that space day to day. I’m more and more just taking it as a given now that someone won’t have much if any experience writing CSS by hand. If they do, never in an actual .css file. Always via some CSS in JS something or other. A strange new world out there.
Honestly I can’t remember half the dom manipulation stuff and at one point I did know it quite well. It’s just been 6 years since I worked on an app that wasn’t react.
It’s useless knowledge for most people now. Like knowing assembly.
I wouldn't really consider anything involving the DOM to be a JS fundamental. That's a browser fundamental, and even then, it's like, what do you want? I can use `document.write('hello world')` and replace the entire body. Or append it as a text node with `document.body.append`. Or create an element and add it. This is a pretty silly question and something people should just spend 2 seconds looking up on the rare occasion they need to do it.
I currently work with devs who've done things like create a Map and then assign properties directly instead of using .set and .get.. I'd say that shows a pretty significant lack of fundamentals
I believe Map was released in 2015 as part of ES6 so while not new, it still feels new in some code bases. Some people also confuse it with Array.prototype.map a lot.
People just assume every data structure operates like an array since it is the most commonly used without realizing the underlying object nature of the language. Like the idea of getters and setters coming from OOP paradigm is lost to fresh devs over the last 5 years using the FP paradigm as their primary means of coding in React.
So yeah some of the fundamental are missing but also most of the time this knowledge probably isn't utilized by React FP only devs in their day to day.
I would assume array methods (map, filter, reduce), callbacks, hoisting, mutability, etc.
I've interviewed a few people who don't know how some of the array methods work, and those are one of the most important parts of knowing how to write Javascript.
What does "across the board" mean? You mention that the article scores for newbie Google searches about XSS in React.
I mean, it's correct that people who ask such questions should spend a year doing web dev without React probably (and maybe learn basic programming concepts). But the people who comment to you about that post seem to be self-selected for not knowing much about JS.
People who know their ropes aren't left with any questions by your article :) and probably know about everything it contains already.
Still, feedback from me: good content, especially for beginners!
If its just the one question then sure i agree... but if it was used as a kind of fun icebreaker question, then I can kind of see where it could be used.
Especially when you deal with unsanitized data - like from a 3rd party API - you're bound to eventually have each of those cases find their way into your if statements/expressions.
Also, this question works for other languages too, as e.g. NaN can evaluate to True (Python) or have an undefined behaviour but still evaluate to true (C, C++) - it's useful to know what is true and what is false(y) in your language of choice, especially coming from another language.
But a different representation in IEEE 754 floating point. If you were building a JS interpreter it would be important to catch that 0 and -0 are different numbers in memory and to hardware operations.
Got me there, as I forgot about it, but I also don't expect anyone to always name all of them - as it's just a probe on how broad was the spectrum of errors a person encountered.
Personally I've never had an issue where that would matter, as BigInt is typically used mostly in isolation. Any avenue for errors appears only when types are mixed or used in boolean statements.
If we're being pedantic, you also forgot document.all. Which is in fact an infinite collection of values, because document.all is a different object in every frame.
about 23-24 years ago me and another senior developer were working on some important parts of the product we were building, and we had a minor task for a company that was paying a little bit, so we handed it over to a guy who was junior but should really have been better (he had the wrong kind of Laziness).
After some hours I saw him walking around with that programmers walk we get when trying to figure out a particularly hard problem. So I went over to check on him.
He informed me that his code to read in the XML file and transform it with the XSLT I had given him worked perfectly in IE but in Netscape there was some sort of problem with the ActiveX control he was using.
So - I figure assuming "JSX works the same way" is the modern day version of that.
When all the frameworks were taking off, I was at a huge company using a 15 years legacy front-end. My background was "traditional" front-end. HTML/CSS/JS and mostly jQuery at the time.
Every time I went in for an interview, the senior devs would always start with fundamental JS stuff and then go from there. I would consistently get comments about how I was the first person they interviewed who could actually talk to basic JS stuff like closures and scope chain. They said there was a huge influx of people learning React and Angular and had no idea the difference between the two or like you said, they were based on JS.
This was back around 2014/2015 and it looks as though not much has changed since then.
was at a bar and i met some guy who was like a year into his first software dev job and somebody was asking us about learning to code and i said to learn html/css first and he was like, "you don't need to know that, just learn react. i don't know anything about html."
i kept my judgement to myself and just ignored his advice. hopefully he's learned html.
I had a similar experience back in the early 2000's.
I was working with a senior developer who was having trouble moving something up on the the page when something else disappeared. He was using asp.net server controls, it was all he knew.
I suggested "just wrap the content you need to hide in a div and style it with display: none, your content will automatically float up"
He answered me with a sort of superior sneer: "I'm a .net web developer, I don't know what a div is, and I don't intend to learn it".
To be fair, that was a different time and MS was trying hard to make web development act like VB desktop development, but still...
This sounds like the complaints from a new developer that's frustrated over the layers of web dev.
React does a fantastic job working with common developer principles such as Don't Repeat Yourself, and Single Source of Truth.
Their points come across as overly vague and lack any true insights into development besides initial impressions.
For a static page it doesn't make sense to use React, obviously. For a highly interactive page it, or another framework is critical to clean, manageable code.
Maybe it's a bit vague or don't have 'true insight', but I would still encourage anyone sharing their feelings, even if they're not expert level insights. React applications turning into a maintenance nightmare and the meta changing under your feet is a common sentiment and I think it's helpful if more people talk about this.
One issue in the frontend space is that React has been the default no-questions-asked choice, but my personal vague, no-true-insight feelings are also that you need a technically very proficient team to avoid it turning into a maintenance nightmare.
Many people work for SMBs, and it feels like there's not a great golden path currently for frontend. Doing a something simpler somehow feels like a bigger risk to the people I chat with.
>For a static page it doesn't make sense to use React, obviously
JSX is a nice templating language. And when you use Deno or Bun you can use it directly on server-side. My server-side components have no hooks and use preact-render-to-string or `renderToString()` from `react-dom/server`.
Also there is Gatsby which is a popular content management system which also allow non-interactive statically rendered pages (as far as I remember).
JS is missing switch/match expressions, that's pretty much all IMO.
And I commend the maintainers of JSX for refusing to extend its syntax.
JSX can be learned in 15 minutes and it is a macro usually used to wrap React.createElement.
You could just as well swap your bundler plugin and use some other type of macro, e.g. sth like Mithril's m.
JSX is a very slim basic concept and I don't know a single gotcha except for the renamed attributes/props that are otherwise reserved keywords (htmlFor, className).
That you can use/see it as a templating language is just a part of its appeal.
I loathe having to use dedicated templating languages, having worked with Mustache and various PHP templating languages such as Blade and Twig.
Maybe "loathe" is a strong wors because most of the time it's easy and just works. But when it doesn't, debugging is a nightmare.
Escaping rules and questions like "what is code, what is a just an uninterpreted string" become unpredictable, and you have to learn useless baggage for each of them.
Same goes for all the JS DSLs using HTML attributes (Vue 2 "templates", which are actually not templates, etc). This is also what turns me off about htmx.
It'a great to throw together a specialized solution for one problem, but not great for libraries inventing unnecessary proprietary languages.
>don't know a single gotcha except for the renamed attributes/props that are otherwise reserved keywords (htmlFor, className).
This is related to `React.createElement`, I think. Preact does not have this problem. For client-heavy web applications I prefer React over Preact (not all libraries work well with Preact), but server-heavy web applications are fine with Preact.
ts-pattern has been a decent band-aid for the lack of native pattern matching, but obviously has downsides that could be avoided if it was built into the language.
That's true. It's missing "a ton of features" but the question is, if these missing features in the template language stop us from building correct and maintainable web applications. Having that said: We are fine with JSX.
Using Razor obviously did not stop Microsoft from building buggy web applications.
I had no idea what Razor was (I'm not a C# guy, I don't like to work on mediocre platforms... (see what I did here?)) so I read about it a lil' bit and could not find a single thing that it does that JSX cannot. Not one.
I suspect they want better condition handling. Because JavaScript lacks a useful conditional expression beyond ternary expressions, condition handling in JSX generally uses boolean operators or ternary expressions. Suppose the conditional logic is in any way complex. In that case, your choice is to use nested ternary expressions, which can be hard to read or to somehow break the condition out of the JSX using a helper function or separate component so you can use if statements in a regular function context. SolidJS added conditional helpers to its JSX flavour to address this issue[1]. The React team seems ideologically opposed to the idea as it presumably moves JSX away from using only JavaScript for handling logic.
>I suspect they want better condition handling. Because JavaScript lacks a useful conditional expression beyond ternary expressions, condition handling in JSX generally uses boolean operators or ternary expressions.
If a condition in JSX gets too complex I normally extract a component-level function and call it from the JSX part of the component.
knowing both i used to be frustrated by jsx's lack of support for plain if and for loops like razor has (eg map and the weird && syntax we general end up with)
of course this idea goes against jsx's implementation (as it's just nested functions) and paradigm of being html in plain javascript rather than an interpreted templating language.
some of the differences i really like (like being able to assign compoents to variables, pretty sure razor doesn't have anything like that).
Or Astro, and plugins for React/Tailwindcss/etc. Components are just nice to work with because of their modularity. Using the ergonomics "most web devs" are familiar with is just nice.
Can confirm the author (not me) has been doing web and system development, including React dev, for over a decade. His complaints are borne of his own frustrations.
While I agree in principle that 10 years of experience can also mean '10 years of being a substandard developer in every way', what basics do you feel are missing here?
It actually is quite suitable for static pages where the content itself is quite dynamic (e.g. from a CMS or other database), especially when rendering repetitive data structures (e.g. lists of items). You use React on the server to render the contents on the fly as static html and serve that.
A good question is "What is interactive?"
Many "interactive" things can be done just with CSS and HTML.
* a list of elements you can select and delete/bulk-edit is feasible with <form>
* any kind of form with input
* hide/show toggle
* tabs
* accordions
Many single page apps aren't really interactive or require minimal JS.
Currently, we're doing things in JS (like forms, pages, tabs, virtualized lists & tree views, hovers, even buttons with JS click handlers) just because our server does not render HTML.
It’s true that a lot of simple apps could just be written using direct DOM manipulation, but you basically write yourself into a corner. There’s no gradual transition from that to any framework, you just have to rewrite your app
Might as well just start with the least common denominator that everyone knows and is easily hired for
I made a paint app with jQuery, and thought it would be a good idea to refactor to React so I could run it on a Next js server and add some multi user support, with later plans of refactoring that to a React native app.
Completely painted into a corner, I gave up after about six hours of trying to get my event listeners to work with React.
It's a shame, because there's so much server side stuff I could be doing right out of the box with Next, but now I basically need to choose a completely different architecture from the one I want because I thought it would be easier to use jQuery.
In all fairness, direct DOM manipulation works a lot better than React for the original app, but now I have to keep DOM state in sync with my server, which is a whole other challenge that React solves quite nicely.
Yeah especially things like complicated forms can get really hairy if you try to implement them by direct DOM manipulation. Things like fields being shown conditionally based on the value of other fields, data being fetched in the middle of form (depending on field values), stupid complicated validations etc.
I love React but I use no state management, apart from useState locally within components.
State management in React is a major source of pain and complexity and if you build you application using events then you can eliminate state entirely.
Most state management in react is used to fill out props and get the application to behave in a certain way - don't do it - too hard, drop all that.
Here is how to control your React application and make it simple and get rid of all state except useState:
Trust me - once you switch to using custom events you can ditch all that crazy state and crazy usage of props to drive the behaviour of your application.
I also use native events in a number of places, and it can work well if you're very strict and judicious with your events, but the danger is always that one ends up with a global event bus with none of the observability or structure that make effect buses work well.
Data races are a specific example of something that happens when you don't have that observability, where the flow of events through the system produces behaviour that's dependent more on event timing than anything predictable. For example, you could have an event that triggers multiple asynchronous processes in different parts of the codebase, that in turn both access or update the same bit of state. This means that the final result of the state will be dependent on the order in which the state accesses/mutations happened. Importantly, with event buses like this, particularly ones built in a more ad-hoc way, it can be very difficult to notice when this happens without keeping the whole application (and all its possible events and responses) in your head at once.
In my experience, most of the complexity from frontend development comes from managing changing state, and one of the key problems is understanding why a given bit of state is the way that it is. I want to be able to easily trace what caused a change, where it was triggered, why it occurred, etc. But event buses can become messy because handling and dispatching a given event can happen anywhere. So even if you're sure there's no data races now, the longer the application exists and the more people work on it, the harder it becomes to ensure that data races aren't happening somewhere that you've not thought about.
That said, I agree that other state management tools that try and solve this can produce a lot of their own complexity. Redux, at least raw and with all the boilerplate, can be painful to use.
Personally, I've found signals to be one of the more convenient mechanisms for this kind of global interaction. Signals are similar to events in that they can be emitted and listened to, but they are more explicitly about the flow of data rather than arbitrary events fitting around the place. This makes it easier to hook into what's going on and see how the data is being changed. There are signals libraries for React (MobX is the classic one here), but these days I mostly just use SolidJS, which is a framework that looks a bit like React, but uses signals as its core reactive primitive.
I'm on my phone, so I can't give great code samples, but with events I'd probably write a separate class/service/tool to handle the cache busting state like this:
createCacheBust() {
// cacheBust here is a reactive getter, not just a value
// Calling `cacheBust()` in the right place will ensure that the
// effect or component will be rerun whenever
// `cacheBust` changes.
cost [cacheBust, setCacheBust] = createSignal(Date.now());
function reloadImage() {
// Update the state, trigger rerenders in any component that used `cacheBust()`
setCacheBust(Date.now());
}
return [cacheBust, reloadImage] as const;
}
export const [CACHE_BUST, reloadImage] = createCacheBust();
In simple cases like this, you can just call this "hook" globally, although in more complicated situations you might prefer using contexts to pass these values around.
In components you can just import these values and call them (or pull them out of a context and call them, if that takes your fancy):
You might say that this doesn't look much different to the event bus version, and that's true, but the benefit is that we've encapsulated the state somewhat. Before, emitting an event could do pretty much anything, and the state it affected was spread out over any component that chose to listen to the event. Now, the state lives in one place, and it is mediated by the exported API. If the state starts behaving unexpectedly we know immediately where we can start our journey to figure out what's going on: the createCacheBust function.
This is just how things might look in SolidJS, but you can also use Preact which merges the React and signal-based worlds in a different way. But either way, I really recommend exploring signals as a way of being able to wrap the event-based logic that you're currently using in a simpler, more state-based parcel.
>> you might prefer using contexts to pass these values around
I'm not getting the thrust of this.
So instead of simple, easy to understand messages being sent around we are now talking abstracted functions contained in contexts to send event messages? Sounds unnecessarily complex. May as well implement Redux.
As I said, you don't need contexts for this, signals can be completely global, and in the example I gave the signals were global (you don't even really need the function).
But the whole point is that "simple, easy to understand" is very context-dependent. Goto, for example, is very simple, possibly the simplest form of control flow you can imagine, and it's also easy to understand at the point that you're writing it down. It just moves control flow to where you want it to go - what could be simpler than that?
But simplicity needs at least some structure, otherwise it becomes chaos. That's the value of encapsulating both the events and the state in a single place, and then providing a limited interface to that reactive state. Yes, it's (slightly) more up-front work to write that interface out explicitly, as opposed to just putting things into events, but it has real value later on when someone else needs to read the code and understand what it's going to do.
However when programming React I try to avoid even layers of abstraction beyond what is already enough complexity.
The argument against events is losing track of where they came from and what they do but honestly I found that using state to drive the application UI was vastly more complex and hard to manage and debug than event messages. It's easy to do a global search for GLOBAL_RELOAD_RELOAD_COVER_IMAGE to see what a message does than to trawl your way throw the harrowing complexity and intertwined complexity of state, props, renders and re-renders.
And when I can, I attach the events to local elements in the component rather than document, to further reduce the scope of the complexity.
Why not use a MobX state class, then just write to state.cache_date? The state is in the parent lexical scope of the components, so no prop drilling or providers.
I used to use events just like this, but once the app gets bigger it’s hard to keep track as the event keys are strings. There is no IDE support for tracking usage (functions and class properties allow jumping to and from usage).
Also MobX tracks dependencies based on reads and auto re-renders changed components. This replaces having to hook up event receivers manually to re-render.
I think there are newer mobx state management systems nowadays (Signals is the new term).
Events and state need not be mutually exclusive. I like Vue’s approach of state going down the DOM tree and events going up. This works really well with Context and custom events that are dispatched by components (vs by the window as you did).
IMO global events can get messy quickly and make it really hard to develop more complex apps where you have the same component in multiple branches of the DOM firing the same events.
This is similar to one method that I’ve used in the past with the BroadcastChannel API. You can essentially create a pub-sub pattern in the frontend. It worked well for microFEs, but now that Preact released their Signals library I’ve moved to that.
Building on top components (un)mounting makes your components impure (it called useEffect for a reason). Suddenly you can't trust what you see because THAT might be the edge case. Unit tests don't work either.
I don't see anything in common with Redux or contexts.
No libraries. No higher order components. No concepts to learn. No weird rules. No complex tracing of props and trying to work out why state updates were not triggered, or were triggered.
Redux is one of the most painful software development experiences I have had.
Just the thought of using Redux fills me with dread.
The event code above simply sends a message directly between components - that's nothing at all like Redux.
the concept is that events subvert React's own change detection. it's definitely more direct than stacking contexts on top of each other (... or Redux, shivers)
but probably more maintainable, after all you can just search for the event name.
I just don’t understand why you’d like react if you like working with events. Sounds like you just JSX? Wouldn’t you get better served by something like lit?
I think react is great except the concept of using a one way flow of props to drive the application via state is flawed and too complex and hard to debug and has cross cutting issues.
React provides a nice application architecture with minimal usage of props and no global state or contexts.
It is not difficult or complex at all to use pure functions and seven hooks. They are documented exceptionally well.
All the complexity author is complaining about he created himself. You can keep the browser router if you want, it can be synced with reactive state using a single side-effect and a single reducer, you don't need to replace it with react-router. You don't need to use Next.js. You don't need SSR or graphql. You can use just regular CSS if you want. This is not complexity that "comes with React", React comes with nothing like that. This is complexity you are stuffing into it.
I stopped writing anything in react the moment they introduced that ridiculous hooks API. Very clear they have no clue at all. There are plenty of other options that don't reach so hard to appeal to functional purist propeller-heads.
I couldn’t disagree more. Having components be pure functions makes testing and developing so much easier, not to mention the reusability of hooks. Class components were a mess. They had way too much business logic and state stuffed into them that it was impossible to maintain any reasonably large component.
Of course you can still write shitty code with functional components and hooks, but at least now the paradigm itself steers you towards more maintainable code
Young dev: it is way too complicated to do something as simple as a todo or hello world app. You have to configure a dozen settings, install 10,000 dependencies and fiddle with too much stuff. I'm going to create a framework that is simple, lightweight and easy to use.
Time passes, framework becomes popular blogs write about how framework X is the future. If you don't have 10 years in framework X you can't get a job. People start using it for things features get added to accommodate needs. People argue saying it's necessary it fits the demand. Framework X becomes a gigantic bloated monstrosity, development slows as useless bureaucratic leeches posing as developers create a "foundation" to "shepherd Framework X towards a bright future." At this point usually the creator leaves or is driven out.
A young developer comes along and says to himself "it is way too complicated to do something as simple as a todo or hello world app. You have to configure a dozen settings, install 10,000 dependencies and fiddle with too much stuff. I'm going to create a framework that is simple, lightweight and easy to use."
The Wheel of Development turns, and frameworks come and pass, leaving defaults that become best practices. Best practices fades to srandards, and even standards is long forgotten when the problem that gave it birth comes again.”
This article is written from a lack of experience of fundamentals and it is not very rigorous, but it's kinda sorta not wrong.
I have been thinking for a while about specialising in teaching how the web came to be, so people who are non-technical can understand enough to commission work, understand proposals, etc.; because I think people have no sense of what goes on under the hood.
But increasingly I think it's junior developers and web-oriented designers who need to be taught it.
(Also the developers of Hacker News: "flag" should be idempotent, surely, and not a GET request?)
I also feel that there's a growing need to teach fundamentals to people across the board. On the other hand, there doesn't seem to be any market for it. So many people become 'developers' by attending 90 days bootcamps to get a job quickly and so many more avoid anything technical altogether because they're 'not a technical person'. So I doubt there's any market for teaching these basics...
> So I doubt there's any market for teaching these basics...
While working through the idea, the most challenging aspect for me has been how to describe the value of it, even though I know what the value of it is.
I think there are parallels, like no longer knowing what is going on under the hood of your car, which has its own anxieties.
Paradoxically I think it is non-programmers who are more interested in the kind of "history lessons" of it -- like, how did we end up here, 10,000 feet view stuff. And perhaps just a small amount of that would stop people being bamboozled by copy-and-paste nonsense in proposals, quotes, project plans etc.
It strikes me as interesting to think about, that if you were to go back in time and ask someone twenty years ago if they knew much about the web, those people, who might be from diverse non-technical fields, might be able to tell you quite a lot they'd gleaned about how it actually works. Because the books on the web then taught you how it worked. Surprising people used to know about domain names and FTP servers.
But nowadays, the knowledge is much higher-level, and in a way that leads people into believing things only have complex dependencies, like React or serverless designs or Cloudflare.
It's like the web needs its own Raspberry Pi movement.
You make good points. The 'history lesson' aspect of it especially interests me, as I am currently pursuing further education in historical research.
Also, something clicked when I read this
> But nowadays, the knowledge is much higher-level
High level is the standard metaphor for 'highly abstracted away from fundamentals' but I think 'highly nested' would be more appropriate. More abstraction levels doesn't always lift you up, and often obscures important stuff.
His points are why I like Svelte. YMMV, but for me it hits the sweet spot of not having to do a lot of stuff by hand like we did in the jQuery (and earlier) days while also not being this massive, intrusive thing.
Svelte, however, has its very specific way of working compared to all the other usual frontend frameworks: virtually no runtime (library) supporting the app and many things happening at compile time instead and via generated code.
It also seems quite focused. If anything is to become bloated, I would expect SvelteKit rather than Svelte, to become larger.
I also don't know how much of the bloat is to be attributed to React vs. its usual friends or their numbers, and maybe SvelteKit actually helps keeping things in order in the Svelte ecosystem.
Svelte has also been around for a while now.
(Note that I have only small experiences with Svelte, none yet with SvelteKit)
I think it's more accurate to say that Svelte can create a build with no run-time for certain apps (so can React with SSR), but for the general case, the Svelte compiler basically builds a custom runtime that only works for your application
Yep, the custom runtime you mention would be the generated code I mentioned.
When I said "runtime", I was thinking of some support library you'd need to include next to the code of your app (which is left intact by React, and mangled to death with Svelte).
> Adding a view library is helpful, but with it these days comes state management, routing, graphql, SSR, hot reloading, CSS-in-JS, and just mountains and mountains of related things just to get your app running.
It feels like the author is confused between react (the library) and the its ecosystem. They don't need all those things in order to use React.
- Routing: Not mandatory. You can just use server side routing. You're no longer a SPA in this case, but do you need to be a SPA ?
- SSR: I actually do not understand the new obsession with SSR. If you need SEO, add a static marketing page, that might be enough for a lot of scenarios.
- CSS-in-JS: just write a plain css file and class names
- State management: useState + context API works for a lot of simple apps.
I don't even understand why "hot reloading" is even listed in the complaints. It's a nicety, not a requirement. It's not even "react".
Did I miss the part where he suggested what to use that's better than React?
At this point we've been through enough front end churn, React is fine. Components, static typing, a javascript/html based templating language. Server and client side rendering. With Next.js my DX is better than anything I've used before.
Vanilla JS? Yea, no thanks. I'm not going back to square one, choose your own adventure custom framework because of your skill issue.
It's possible to write a whole load of very clever things in vanilla JS, but it's not always a good use of time to do so, and it is not a very easy way to develop things in large teams, without building up an abstraction layer with getters and setters that is not appreciably better than a minimal reactive framework.
The one-way data flow in reactive frameworks is the bit worth fighting for (and fighting over).
Vanilla JS is better these days than when React first arrived. ES Modules are natively supported in browsers now and give you much of a component system.
Though to be fair, rather than using Vanilla JS alone I did recently write my own React-looking but not React-like view engine: https://worldmaker.net/butterfloat/#/
I too am not going back to square one, and I find React to be fine for e.g. a Gutenberg component.
But I'm looking at tiny web interfaces for microcontrollers at the moment, and as an experienced Vue developer I find petite-vue and a classless CSS framework an appealing compromise for designs without a build step.
You can use Preact + HTM to skip the build step, too. It's very nice for the middle ground where DOM management gets annoying but adding a build process would be difficult.
Back to square one? Not at all. ES6+ makes writing pure JS quite easy. I've managed to put together multipage forms, with end to end validation and conditional rendering, in just a few hours. Doing the same thing would have required a full blown react app.
This just sounds like a bunch of vaguries that could be written about any framework. And React works fine for small projects. There’s no need to loop in a bunch of dependencies like css in js or graphql either I’ve been using it for years.
I have to agree that with the introduction of React 18, and the new versions of Next and SSR everything has taken a turn for the worse. I’m sure it’s all very fancy and advanced, but it’s become completely impossible to reason about.
I feel the same. After a year of not touching Next, I came back last week to find it’s unrecognizable. It feels like there are 10 ways of accomplishing the same things now, and Next tries very hard to make none of them feel like the right way.
Want to structure your code? There are 4 ways to do it. Want to fetch data? You can use route handlers, server components, or server actions. Don’t forget to choose one of the 5 ways to cache and revalidate data! Want to show a loading indicator while the data loads? There are a few ways to do it, but be careful because some ways depend of parent components being server or client side! Not to mention all of the “unstable” apis.
I appreciate that they want to make it easier to build incredibly efficient applications, but now there are so many options and so many ways to shoot yourself in the foot that I’m stuck with choice paralysis.
IMO a good framework should have one and only one obvious way to accomplish something. More advanced use cases should be hidden away in the reference documentation or left as an exercise. That’s why frameworks like Django and Rails were so successful.
The new Next has jumped the shark. I wish there was a good alternative right now. I feel like they’re building for FE devs who are scared to learn BE dev.
React has lived long enough to become the villain. It definitely pushed web apps in the correct direction, but it has grown some nasty kludges to account for things that were very hard to foresee. Choosing to use it nowadays for greenfields projects comes across as cargo cutting to me.
I somewhat disagree that the approach is ill-suited to simple sites, server-side JSX is a strong step in the right direction. If you're using it on the server you may as well use it on the client, even for minor interactivity problems.
> I somewhat disagree that the approach is ill-suited to simple sites, server-side JSX is a strong step in the right direction.
Wow that sentence made me want to throw my laptop.
I want you to build me a site that can be cached (think basic product shopping cart page) and then do the JS/hydration magic after the user has seen the render. Go ahead, and take your time, it's not a fun exercise in react.
As for JSX on the server side... It was a shitty idea to mix presentation and code when PHP did it and got laughed at, JS/JSX isnt special. Templating languages are LIMITED for a reason. You know code/content/presentation all being separated is a good reason to do that...
I was referring to static sites, which the post talks about quite a bit. JSX is just a sane templating language.
Much of the hydration stuff is accidental completely, I would argue that all is with the advent of search engine scrapers that give the page some time to render. The goal of including associated data for the first render is essential complexity - it can save up to 200ms of latency, but there are simpler ways to do that (such as data islands, early hints, or SSE). At that point JSX is, again, nothing more than a really good templating language.
Data islands are my choice because they worked in the 90s meaning they will certainly work today. XML back then, but JSON works just as well. Of course, hydration is assumed to be the only solution for the react-size-fits-all crowd.
This feels like some pseudo intellectual take. Choosing react for new projects is not “cargo culting”. It’s a proven and effective choice with a huge market to hire from.
Meanwhile whatever server side renderer of the week framework you pick could be old news and abandoned in 5 years.
As someone who has been doing React for nearly as long as it’s been public, the honeymooon is definitely over. Hooks were supposed to save us, but now my projects are more complicated and harder to maintain than the old class based components. My team is constantly fixing useEffect and useCallback bugs. UseEffect just traded one foot gun for another.
As Vue and Svelte have shown, maybe it’s time for react to include a compile step to automate some of the boilerplate/tedium and reduce avoidable bugs.
It's amazing how much developer time is wasted writing components. I have to imagine that these jobs are at risk of being disrupted by AI though. If AIs can create designs, then they should also be able to convert design specifications into mostly-complete components. Expect the tech to exist by 2025 and disruption to component developer employment within a couple years.
You can use GPT-V to create functional components from images directly:
There was an open source project (https://github.com/abi/screenshot-to-code) that I borrowed the prompt from and made a custom GPT for myself where I just drag and drop the image. It’s not perfect but it’s pretty great overall!
The hard part is usually not getting the component to look like the design but rather the fun process of discovering all the interactions nobody thought about while they were focused on pretty pictures
Here is the number 1 thing you need to realize about web development: it goes from simple article websites to ecommerce to full blown applications like Photopea or Figma.
People act as if it's all 'web development'. And then you get things like "We need to move back to server side rendering". And I think: why the hell did you think using a front-end only framework was ever good for your e-commerce website?
It boils down to this: figure out what you're actually doing, and get the best tools for that.
React is an awesome framework, but if you're building a simple blog, why the hell would you use that?
I've done front-end with PHP, ASP.NET Web Forms, Razor, jQuery, AngularJS, Angular and React and React was by far the most enjoyable experience I've had. It made front-end development tolerable and even fun. I've never seen React code that was as horrible as Angular one.
But, but, what do I do with the EnumerateAll@injectables plugin that I bought for Jetbrains? Do I have to not write all these @s??? What is that key in the keyboard if not for @singleton@injectable@module@component??
This post is just a list of grievances that don’t convince me in any way why I don’t need it.
Maybe, I don’t care if it’s “overengineered” or maybe I don’t need something fast or maybe I need an abundance of talent to work on it. There are plenty of reasons why it might often be the best choice.
I feel that the documentation is often overlooked. In react I’m always confident that if I can think of something someone has likely already done it. Can’t say the same for my experience in the newest version of angular (I will admit that might be due to my noobishness)
> Adding a view library is helpful, but with it these days comes state management, routing, graphql, SSR, hot reloading, CSS-in-JS, and just mountains and mountains of related things just to get your app running
This is wrong. If you want to build a web app in React you don't have to use anything except state management, which you need in absolutely any stateful application anyway and which can be a literal one-line React hook.
The point about not building websites in React is valid, but...just don't do that if there's no advantage? This is about as helpful as saying you don't need to store binary blobs in Postgres. Well, no, you usually don't, but I'm still going to use Postgres for what it was actually designed to do.
i get a massive distaste on what bulky behemonth of a mess nextjs is along with the ssr etc. i fucking hate it. this bleeding edge stuff is whack.
but one thing these geeks got right is how mature the developer tooling is around react. it just all fits well along with eslint, stylelint, vite, tailwind, etc. this cutting edge stuff is good.
React's original problem was that its users were expecting a framework and got a library. It's not semantics what matters here, but the fact it didn't take care of fundamental parts of web apps, leaving those to be handled by someone else. And the result was often a buggy, half-working slow app, due to a mismatch of different modules. In my opinion, it is kind of like the "C" of web languages, in a way. It is powerful, but certain concepts are difficult to master and leave out too many important features.
So I have a react related question regarding the following stackoverflow solution. I find myself ignoring the warning in useEffect fairly often but wonder if the solution provided is a reasonable one or not?
The situation I have in mind right now is a search field which updates a local useState value. When the user hits enter to trigger submit (or clicks submit), I want the useEffect to fire. At the same time I want to be able to clear the field and submit via another button.
I am probably not explaining it well but the missing dependency becomes a pain point in these situations. Is useRef basically what people end up using to work around it?
As for what the article above says, I do agree that the churn in the JS world in general is very exhausting. I guess it is filled with a lot of young "talent" who have endless time and energy at their disposal.
the churn is because iteration-by-iteration we're moving closer to something that is just right. but that goal is also constantly changing. (not to mention that the webdev community is not a hivemind, so it makes sense that there are many tools, and many new tools.)
and after a few iterations it makes sense to do a jump in some non-functional metric (vite, deno/bun), or do a vertical integration (vercel), and then new tools target those platforms, and ...
if it's exhausting stop chasing the new shiny thing, and just use Angular like normal people. or HTMX :p
Pretty much forced to build production systems in Angular in my day job. But typical process for prototyping new speculative functionality is:
$ npm create vite@latest
> React Typescript
And then blindingly fast building out super hacked functionality with sub-second Write -> Compile -> Reload times (joyous vs production Angular build infra).
Then after a few demos and iteration, take it all and build out a well structured Angular app.
Signals + @if syntax in templates makes modern Angular development pretty good. And the strong separation between styles / component / template ends up creating more maintainable large code bases where a lot of engineers are contributing.
Time to go on a tangent, does anyone think useEffect was good idea? In general I've found "side-effects" libraries like rxjs & saga's being the main cause of bugs in react codebases, and useEffect a good second.
This sentiment is trendy (and a bit edgy among people who still refuse to learn modern JavaScript), but it's missing the point. React is the first JavaScript platform that feels well engineered for the web.
"React suffers churn" -> goes on to talk about a lot of things that aren't React.
"React should stay in its lane" -> React has a router to better manage lifecycle state. And it's simple and flexible and easy to work with.
"React's talent pool is diluted" -> lol
"React is not fast" -> This is true if you are comparing to e.g. htmx, but except for a bulky first load, React is just as fast as anything else.
"React is overengineered" -> React is simple. It's good because it's simple. The data flow and rendering flow are intuitive once you understand them, and once you think in React, things become so nice that working with plugins that aren't React-y becomes kind of frustrating.
React is a great framework for app dev. It has nice conventions, a simple learning curve, a good ecoystem, and good corporate support. I don't need React, but I use it because I like it.
People detest Word because not every file is a document. Perhaps you are too old to remember, some hopeless folk writing their code in a word document like it was a good thing... (it had macros and viruses even! What a fabulous program)
> React is simple.
Its not simple, though. Js is a bloated nuclear wasteland at this point, so it might not look half bad compared to the other mutated monstrosities lumbering about, but that's it.
> manage lifecycle state
As soon as you have to say that, you aren't in simple land anymore. You're in "I have 10 features and 100 states and OMG don't break production" state.
The point about "dilution" is especially salient. Call it elitism, or whatever, the popular framework/language attracts the lowest common denominator - unpopular languages don't necessarily save you from this issue, but they make it more likely that someone took time and effort to care about being a good developer, not just an employed one.
That's what he said. He said it's good for app dev. Sites that aren't an app (or web app, or SPA, or whatever we call those things these days) should not use react as it makes no sense as a choice for that case
This is something I see people criticize react a lot and it makes no sense to me; "React isn't good at a static site/fast HTML page/non-stateful and complex app!!" It's not supposed to be! It's not for that. It's not a criticism of the framework. I'd love to read a criticism of the framework for what the framework is used for: complex stateful web applications.
This one in particular always seems to be pulled out by people advocating for yet another new framework. I don't do much frontend these days...for like a decade now, but as a mostly outsider who occasionally dabbles, React has been a constant for a long time now. The latest stuff in Next looks fantastic, in the real world we were never able to build anything nearly as nice as what is possible these days. There's a lot of historical revisionism and rose-colored glasses being worn these days, but the truth is that most web apps have always been garbage, and that will probably never change either.
The library API itself might be stable, but the ecosystem is not. And that ecosystem has vulnerable libraries that should be updated.
And that's not even going into using a big component library, like Material UI, which might be its own nightmare.
This is something I've dealt with a lot personally, and I've made a good attempt to avoid unnecessary 3rd-party dependencies. But the huge churn continues in the build tooling, testing, linting, etc.
React rendering can get very very slow. A classical example are inputs that update very slowly when you type something. "Best practices" lead us many times to this when we round-trip the whole state from input change event, to global store object, immutable changes and back to the input. You can fight it with React.memo and by just mutating the state in-place.
Recently, I found valtio helpful as it allows to hook React components to rendering for parts of the global state.
Also all this useEffect(), useLayoutEffect(), and when it's not enough useEffectEvent() [1] and useEvent().
I don’t know about simple learning curve I feel like it’s quite a different paradigm especially compared to vanilla. Not necessarily difficult just different.
In my experience the sweet spot nowadays is to use a traditional batteries included framework such as Django/laravel/rails with Inertia, which basically just replaces the template part of those frameworks by a modern components framework such as Vue, react, etc.
We are using this approach in one of our projects at work and it’s been working great.
This sounds good until you want to actually get things done. I don't think of React as merely adding needless interactivity, it's also an excellent view engine. It's extremely easy to get a site up and running with easy to read and maintain code with React.
Technology builds on top of itself. Might as well use the things that make you more productive. The DHH ideology of anti-modernism makes some sense in some cases, but most of the time it doesn't hold up. Thank god I can deploy my static site React app to S3 with some GitHub actions and don't have to FTP a whole site into some Linux server I pay $5/month for.
I like React, but I didn’t quite figure out the “additional” ecosystem - what do you use for managing the communication with your backend, for example?
DHH never suggested to host a static site on a Linux server. He only says that most (database-backed) applications could do without frontend frameworks like React.
The alternative to the „static site React app“ you‘re hosting on S3 would obviously be static HTML.
I have been programming since 2008, but I truly started my professional webdev career in 2014. The company I started at was providing software in a B2B-sector. Very boring, very non-startupy. They were considered innovators for doing webapps and SaaS in a market where everybody was used to win32 UIs made in Delphi or C++. The tech stack my employer used was Java EE, PostgreSQL, with a frontend in EmberJS. The prevailing view at the time was that we knew how to do applications on the backend with MVC, and that 'if we just figured out how to MVC in a JS-framework, everything would be fine'. Some went with Angular, some with EmberJS. Build steps for frontend were in its infancy, we used Gruntfiles to just concat everything together essentially.
When React started to gain traction, everybody scoffed at them. JSX was weird, uni-directional data flow was weird, ES6 classes were weird, too many building steps were weird. But it quickly became clear that this was the way forward. Traditional MVC approaches quickly failed once you got out of the example code and into more complex use cases. Which brings me to my point: React was better IF-AND-ONLY-IF your webapp needed to do more than basic forms.
React was never meant for consumer websites. It was never meant to be the default tool for anything on the web. If you wrote a web application, something complex, something with forms, planboards, custom UI, then yeah, it would be a sensible choice. It was meant to solve the problem that doing two-way binding of data is incredibly difficult if you have anything more than some standard form components.
The reality of the situation is that innovation in frontend websites (as opposed to webapps) has mostly been standing still, as everybody just switched to using React. CSS has gotten much better, but doing something like a form rendered with PHP + some validation with JS is still a pretty painful experience. HTMX is probably the best attempt I've seen, along with Elixir and the Phoenix LiveViews.
Most of the effort seems to go into writing a bunch of libraries for React to solve the complexities of having to deal with a complex set of tools for writing complex webapplications. These abstractions tend to either be complex themselves, or are leaky.
I realize my next sentence might as well be 'get off my lawn', but I really hope that devs stop focussing on writing the next state management framework, or routing library, or even rewriting existing things, and just try something to actually move dev forward. Open source a kit of sensible standard components including styling for webapps. Write a simple JS tool for some form validation. Show your barebones NodeJS app rendering HTML and processing forms in an PHP-esque way, give it a logo and a fancy name, chuck it up on GitHub. Don't try and combat complexity with more complexity. We have all the tools we need to write complex webapps. Please make simple websites easier, so people can stop complaining about the complexity of the complex tools meant for complex use cases that they don't need for their simple case.
React is great; many use it badly. This is a tired debate, and the author offers no solutions or practical advice. This is someone who is tired after refactoring a badly written react application.
I work on a badly written react application. I sometimes sift through our microservices written in go, ruby, and Java. They're badly written too. This is not an indictment of those languages or whatever framework or technology was used in those services. Business requirements change, engineers change, and refactoring doesn't give management anything to brag about so nobody gets time to clean up the mess.
Complaining about the "churn" is even more asinine. React continues to support more usecases. New frameworks and technologies are competing and challenging one another to improve. God forbid we might have to learn something new.
I don't think it's possible for a framework to do all of the following: add functionality, preserve existing functionality, and reduce the possibility of dubious implementations.
Also, I do think packages like those from tanstack have made it easier to implement react well. From what I can tell, most people's bad experiences with react come from applications which incorrectly use redux or similar global state as a cache for data from the server. The new Redux Toolkit Query and similar Tanstack Query approaches to handling server state are much more manageable, and in conjunction with appropriately using URLSearchParams you can often get away with no/minimal global state.
I hate Next.js because they make it extremely difficult to deploy an SSR app anywhere except Vercel. You basically have to use the Docker image to deploy your SSR Next.js app. I prefer https://remix.run or https://vike.dev
However, if you just want a static site, Next.js is great.
Astro is great, using it for my blog site and. I have a mono repo setup React SPA and Astro For Blog. I can create a reusable component in React Repo and reuse in Astro blog.
You could also write native astro components which are very close to vanilla html css with added benifit of making reusable components and scoped css.
And you can also use svelte or vue components.
Honestly, you can use Astro and then still use React if you want. Doing so would be similar to next.js in some ways, though you need to hook up an adapter if you want server-side rendering
What is the challenge you’ve had deploying SSR Next, and how does it relate to docker? I’ve only used it in docker (I like docker), but I haven’t seen anything in about Next that seems docker oriented.
Because of how Next.JS builds, you can't just deploy it as-is to something like AWS Amplify or Elastic Beanstalk. For example, if you attempt to deploy to Amplify, you'll get a bunch of 503 errors on SSR pages because of Cloudfront permissions. The static pages work fine though. I'm not exactly sure as to why you can't just "npm run start" on a Next.js app on a deployment service like ELB or Amplify. Perhaps because of the extra SWC compiler Next uses for builds?
I believe Docker works because you're doing "npm run start" and containerizing Next.js, essentially proxying the server to then serve to the client. Basically running it on localhost. For example, you can run Next.js on EC2 if you want, but you have to proxy the connection to allow the client to connect to it.
Again, I'm not an expert as to why exactly it doesn't work - I just know that it doesn't work the same way a simple node app works, which therefore adds a ton of steps involved that don't make it worth it to me.
> as a relative newbie to web dev (with limited time and focus), is Next.js my way to go?
Obviously "it depends (TM)" on a bunch of things but for most of those things, Next.js is a safe bet, sure.
It's a (the?) leader in the React framework space and the ecosystem reflects that (e.g. most problems or decisions a newbie would run into is likely to have a trove of docs/blogs/tutorials/ect. available to get past them quickly, plenty of options for hosting, marketable as a skill if that's what you're into, fine DevEx all things considered, it'll likely be around for quite some time even if vercel shuts down tomorrow.) The same is true for React.
I have both Next and Remix projects and I far prefer Next. While Remix is cool, and they were kind of the original, their build and dev process has become really bloated, so any change now means waiting a minute for the whole server to restart.
As someone with just limited React knowledge I recently started with Next, got stuck with something and moved on to Svelte. It was really easy until I ran into some errors there and eventually came back to Next.
Svelte is certainly easy to pick up, compared to anything React oriented like Next IMO. That said, the issue I had with most of these frameworks were integrating other libraries into them and quite a few of them seemed to not match with whatever version either the framework was using, or the libraries themselves were outdated.
Then again, I'm a noob at this so it most likely could have been my lack of knowledge.
Any fool can come up with a complicated solution, but the best mind comes up with the simplest. A man I respect once said to me.
React is just another example of how rot takes over what is good. And people confuse loud with popular, popular with good, easy with simple, and tedious with merit.
I explained that I preferred not to build and add a React based tool to a profitable Vanilla JS app. The package included dependencies for Postgres. The purpose was to spawn a modal dialog and dispatch requests to the selected service. All of the core functionality could have been provided by a single JSON file describing the possible endpoints. Of course that kind of elegance was nowhere to be found.
The discussion progressed as you'd imagine.
"NPM ecosystem is the biggest developer ecosystem in the world", he replied.
NPM is a nightmare that makes old style C++ dependency management look like a next-gen wonder.
It's hundreds, thousands of silly dependencies taking countless disk space, and a waste of time "minimizing" what should have never been there in the first place.
I avoid Node.js like the plague. I feel nauseous just thinking about that.
This risk with using the simple tech to start out is that you are one feature request away from being under engineered and will have to rebuild the whole thing.
I like react but I agree with these points in the article
...Why is there always a new way of doing things?
...Why am I learning the same thing but in a different way?
...Why was the "old" way inferior?
...Why change at all? Browsers don't move THAT quickly.
"...Why is there always a new way of doing things?
...Why am I learning the same thing but in a different way?
...Why was the "old" way inferior?
...Why change at all? Browsers don't move THAT quickly."
Welcome to the rest of your software engineering career.
This is a very common misconception. React was meant to provide one-way data flow. With an app built directly on the DOM you have to deal with the DOM having its own state to manage on top of the state your own code is storing. You have a list of comments in a variable, and a list of DOM elements for each comment, and nothing but your own code is making sure they stay in sync with each other. React changed things so that the state of the DOM is always derived from your own app's state, which eliminates what turned out to be a pretty tedious and error-prone amount of work in complex web apps.
It wasn't the first to provide this but its API was unique and compelling vs existing alternatives. The virtual DOM, server-side rendering, etc. are not things that make React faster than non-React code, they are things that counteract the inherent slowness in React's design to make it competitive with non-React code.
Watch the original JSConf talk where React was publicly announced and released, and notice how the talk is mostly about the one-way data binding, and the virtual DOM/reconciliation are mentioned in the back half as ways React catches up to non-React app speeds: https://www.youtube.com/watch?v=GW0rj4sNH2w