I feel like there are 2 Reacts (at least 2 that I know of, if not more).
I learned jQuery long ago, then how to get most of what I wanted done via document.querySelector/etc instead since it was more "lightweight", then I learned React "class components" with render() and componentWillMount() and it was a big leap forward.
The "major breaking changes" (semantic versioning wise) to move components to functions (instead of implying it's just a class with render()) and then hooks on top, it almost invalidates most of what I learned about React initially. Which is fine. The community reserves the right to grow however they want. I was just surprised when I recently revisited it. The only common concept was basically JSX and "view/render state/props + actions on events".
I don't think many would agree to this but I'd argue the changes are so radical that they almost should've called this new React something entirely different. It would help. Saying "I know React/I have React experience" is basically in need of nuance like "I have React in 2018 experience, and 0 React in 2023 experience, therefore I don't actively/actually know current React best practices or how to even do a small TODO hello world list example".
I sometimes feel like there are three. The class components way, the hooks way that everyone has been doing it up until a few months ago, and the hooks way that the beta docs say you should do it. Maybe those last two aren't different enough, but the clashing philosophies around useEffect are enough to require massive refactors.
EDIT: I'm referring to how the proper use of useEffects is to almost never use them. They're for side effects, and they're not a tool to just "re-render when these dependencies change". But to do this right, it requires a re-wiring of the mental model of how to do React, at least for many people I've come across.
This isn't a recent development. People misusing useEffect just to update state has been a thing in React since they were introduced, even though a close reading of the original hooks docs should have conveyed that that's not what they're for. I think the new docs certainly make it clearer what the correct usage is, so now lots of people are finding out that their mental model isn't quite right.
Some of this predates the introduction of hooks, as much of the useEffect misuse is identical to the way people misused componentDidMount/componentDidUpdate/componentWillUnmount.
I don't think you're right to say that you should almost never use them. You should use them for doing the things which they're designed for, like attaching event listeners or dealing with timers (neither of which are that unusual in my experience). But like I said, they've never been a tool for dealing with rerenders, and the React team has been trying to explain this to people for ages. The original docs did explain this, but it was less clear than the new ones.
Exactly, this is the same as saying Redux has two methodologies, the "setter system" and the "event system"; since it wasn't that well documented initially doesn't mean that the setter way was ever recommended (it's not). In fact if you watched the Flux youtube talk, something highly recommended to learn the philosophy behind Redux, it was pretty clear.
It seems mostly expected to have a framework or library in place that takes care of data fetching for the root component.
The new docs emphasize this, I guess mostly to make users think twice about building their own hook and to make it easy to move initial data fetching to the server.
Frameworks include next.js, remix or vite-plugin-ssr (the last one is maybe an outlier, as it deems itself a library).
Often fetching is tied to routing, which makes sense.
If routing is not needed, AFAIK the go-to solutions right now are react-query or SWR.
If none of that fits and the requirements are either very simple or very custom, it should still be possible to manually pass props to the root component.
Looking this up in the docs, the big caveat of this unconventional approach is that props would not be reactive, the root component would have to be manually re-rendered:
For what it's worth, "the deps being the things sent to the query" is fundamentally correct. What were you doing wrong before and what are you doing now? There are alternatives to making queries with useEffect which can result in a better user experience. Were you alluding to those?
One of the sources of confusion I see the most around effects is that people still think of them in terms of components mounting and unmounting. However, effects only care about running, cleaning up, and maybe needing to run again. I can't think of a case when they'd need to know about the component's mount/unmount behavior.
For effects, the main things to consider are:
• Can this effect be fired unconditionally, and if not, what could change in the system to make its result inconsistent/outdated with the new state of the system?
I think the "new way" was always the intent. If the past norm is different, it was probably a communication issue (which the beta docs are trying to address)
It’s very clear useEffect was created with a certain purpose and then the React folks realized that was a terrible use of it and changed the purpose of useEffect.
And this would have been fine if they had been upfront about how they were wrong about useEffect and how now this is the correct way to do it. But instead, they’ve at best kept silent about this transition, and a lot of people strongly attached to React have decided to gaslight everyone else about useEffect (I’m a huge React fan… it’s my default UI library but that doesn’t mean I’m ok with gaslighting over transparency).
And the easiest way to prove this is to compare the docs.
> useEffect is a React Hook that lets you synchronize a component with an external system.
Synchronizing with an external system is completely different behavior from performing side effects. And we know the original intention was to perform side effects and not sync with external systems because the name of the hook is useEffect and not useSyncExternal.
Unless the React team always had the new intention but deliberately decided to mislead everyone through the original documentation and by misnaming the hook, but I don’t think even the biggest React hater thinks so poorly of them, and I’m a fan.
I mean, I would argue "synchronizing with an external system" is almost synonymous with "causing side-effects [on render/state change]". Maybe "synchronizing" is a narrower subset of "effects", but I think that's less of a change of the intent and more of a refinement
And I do think the team has been refining this conceptual territory as they go. React is a pretty unique programming paradigm at this point, there's lots of uncharted territory. Following Dan Abramov on Twitter, he works through concepts out loud, having new realizations about how the primitives they've created fit together, what their implications are, metaphors for thinking about them, in real-time. I think they've got a very clear direction at this point, but they haven't turned over every stone along the way yet.
> It’s very clear useEffect was created with a certain purpose and then the React folks realized that was a terrible use of it and changed the purpose of useEffect.
I've compared the docs, and I don't think that's clear at all. They definitely refined their messaging, but the legacy docs show the same sorts of examples that are either shown in the new docs or described[1], such as subscribing to an event system or updating a bit of non-React UI. Could you give some sort of example usage that they encouraged before but don't now?
> Synchronizing with an external system is completely different behavior from performing side effects.
No, synchronizing with an external system is exactly performing side effects. It is a change in document focus from a description that focuses on what it does to one that focuses on the purpose for which it does it, but all synchronization with an external system is side effects and the vast majority of side effects that aren’t incidental to imperative program structure (which functional components avoid) is syncronizing with an external system.
I haven't tried asking GPT4 a bunch of react questions yet. I wonder if its advice is generally in accordance with the "new way", given the training data cutoff date.
They may be referring to React 18 + Strict Mode meaning all useEffects can be called as many times as React wants. People before were writing code where useEffect on [] worked like onMount and was only called once.
The entire hooks "thing" felt like a case of the library authors being too clever.
Having components with lifecycle methods called at known times by the framework is a perfectly straightforward mental model. It's worked just fine since the beginning of time. iOS still uses it.
I remember investing hours (and days and weeks) migrating old code to the "new way" or trying to get some simple thing "working with hooks." Other than being able to share in the authors' feeling of smugness over the unnecessarily-convoluted mental model when we finally got it all working, I genuinely can't recall any value we got out of the whole investment.
I agree. Hooks felt to me like an attempt to go all-in on functional programming when components are perhaps easier for many people to think about as classes due to the unavoidable need to have state in the component. It seemed like an attempt at purism that, instead of making things simpler, made them, at least cognitively, a bit more complicated due to the irreducible complexity of state.
My experience has been the opposite. With hooks, it's now possible to decompose a concern and modularize it in full. Having logic for dealing with a concern spread over willMount/didMount/shouldUpdate/willUnmount was a total mess. It's bad enough with one concern, but if a component has 3 or 4 concerns that span across the lifecycle, it quickly became unwieldy. And for all the complains about people using `useEffect` wrong, I saw just as many people using setState calls in lifecycle methods and crazy things happening in mapStateToProps of class components.
In the end, hooks have greatly simplified things for me.
> Having components with lifecycle methods called at known times by the framework is a perfectly straightforward mental model. It's worked just fine since the beginning of time. iOS still uses it.
What's so infuriating about that is the documentation basically told people, hey instead of doing this, use useEffect the way you were using these methods.
When you have to rewrite the documentation to basically tell the world "you're holding it wrong" then it says a lot about the thought that has (not) gone into designing the feature.
And that's why I think I'm done with React for now. It just does not spark joy.
I'm not sure about the clashing philosophies, but useEffect is certainly a "nexus of difficulties" about learning and using React (with hooks), in terms of the mental model it requires, knowledge of not-so-obvious JS concepts like closures, etc..
I think it’s more a matter of how the JS community has grown in general. The whole “class” thing is something a lot of us brought into it when we came from other OOP languages, but in 2023 it is very rare that it is “better” to build a “class” than to simply build the functions you need.
As far as I know you can still trundle on with some of the old react, but at the same time, things change. It’s not like you’re coding C# similar to how you were 10 years ago either. I know that having been away from it, it was interesting to see everyone using “var” instead of types as an example.
I dunno... when you're building a hierarchical tree of nameable components and several, ahem, instances of each nameable component might exist, and these need to respond to signals, that seems like a case when it's non-crazy to use classes.
I believe OOP is generally overused (no, you don’t need a zero-member class to provide related functions; static class members are a code smell; etc.), but I don’t follow what you’re saying. From my perspective as someone who is just learning React recently but has a decade’s experience in C, C++, and Rust, the programming model doesn’t make any sense to me. The functional paradigm used by React has the same fatal flaw as OOP does: rather than making state management simpler, it attempts to hide it (OOP hides by “private” variables, React chooses to hide it in “hooks”). Both seem absurdly complicated to me. There’s no need for classes with trivial setX() methods, and there’s no need for hooks either, to perform what is essentially a variable assignment. They make the code more complicated to read and write, and increase cognitive load, IMO.
A component that has some state associated with it, such that manipulating that state causes certain side effects, seems almost custom-fit for OOP. The functional style does not seem to fit the domain.
Classes and types and methods exist for a reason. They're not "old" you don't "grow beyond them" anymore than you "grow beyond" functions, constants, threads, or files.
Try stepping outside of JavaScript for a while, broaden your experience.
I think we may be talking a little bit in two different directions, because when you write this:
> Classes and types and methods exist for a reason.
What that reads like to me is actually the exact explanation as to why the JS community has fallen out of love with things like classes. Because JS doesn't have static types, and without those, well... Classes don't actually exist. At least not in the way they do in other languages like C++. You can pretend you're working in a regular OOP language, and use the prototype object like you would a C# or Java class but since you don't have static dispatch at compile time, you're frankly playing this part of JS as a weakness instead of a strength.
Which is why the JS community has been "growing beyond" classes.
If working with classes in JS is more comfortable for you, then I think you should do so, but ultimately a JS class is just a function. Once you grow comfortable with working with modules and functions, you're very rarely going to be writing classes when working with JavaScript. You're still going to do so from time to time, when it makes sense, but often its both unnecessary, less efficient and harder to maintain something that is build like a C++ class rather than than a JavaScript function. While working with JavaScript, being a key part of it. This is not an attack on OOP in general, just an explanation as to why the JS community has "moved beyond" pretending JS is an OOP language the same way Java is an OOP language.
> Try stepping outside of JavaScript for a while, broaden your experience.
Uhh yes, classes in JS is just function, but it forces you to make a strict definition on how the set of functions will behave, in opposite of defining functions and tied them up individually.
If a thing need properties and methods to operate, defining it as class won't make it harder to maintain than cleverly do it with functions and object.
> but it forces you to make a strict definition on how the set of functions will behave
This would be true if JavaScript had static dispatch, but since it doesn't, everything you do with your class is mutable all the way up the prototype object chain. One of the reasons this is harder to maintain, is because the "strictness" you think you build into your code isn't actually there unless everyone who works on your code after you follows the same rules you did. I'm sure we'd like to live in that world, but I doubt we will.
It's slightly more now with private members, but still prototype based inheritance and definitely not the same. Composition will still usually perform better all said.
If you want something more, better to use TypeScript or step to something like Rust+Wasm.
> A JavaScript class is syntactic sugar for prototypes, not functions.
Again you're basically speaking into exactly what I'm trying to say. Because what are JavaScript functions? It is also a prototype. I'll try to put it a different way. The JS community has "moved beyond" classes because they are functions. Both classes and functions are prototypes, but functions are often easier to work with, more maintainable and more efficient.
I'm not trying to say that you should never write another JavaScript class in your life. I write them myself when it's prudent to build things in a structure that resembles classical OOP. The reason I don't personally use that sort of coding style, if I can avoid it, is because it's an act. It looks like classical OOP, but everything is mutable at any time which means it's very easy for consumers of the code to break it by accident. This is less of a problem when you build things as isolated modules, based on individual functions, because there simply isn't any complexity to "misuse".
This is sort of similar to why the virtual DOM became so popular in frontend JavaScript. Because it's harder to work directly with the DOM itself. It's not necessarily better to use functions, it's just "safer", because they come with less risk of someone doing something bad by accident down the line.
Try writing some code in not just JavaScript but also C, C++, Java, and others. Classes aren't some relic. You use prototypes in JavaScript every single day.
You're still just blowing past "the JS community".
To fill you in on the context of the thread you inserted yourself into, classes have fallen out of favour _in JS_. It's pointless to say "but they're still used in other languages!" because we're not talking about other languages, we're talking about JS.
I, too, am talking about JavaScript. Everything in JavaScript is prototype-oriented whether you ignore it or not.
You can choose to write functions for everything, but you're still always using object prototypes.
There are several large popular libraries in JavaScript which do not orient themselves around functional object orientation, too. So you might work in one corner of JavaScript where all you experience is functions, but that's not the case everywhere.
They haven't "fallen out of favor," whatever that means.
Yeah. Functional components are right sized. You can still decompose & hack off pieces nicely, into helpers or hooks.
Just because CS has heavier weight classical structures we can apply doesn't mean they're better. And underneath a lot of those ideas were more lambda-calculus ideas that correspond somewhat with functional components.
> I was just surprised when I recently revisited it.
You can STILL write React like you used to (with class components). There haven’t been any major breaking changes. The transition was very slow. It was only recently that they even changed the docs.
You’re complaining that they made changes to it half its lifetime ago after you walked away from it and now you can’t just go back to the way it was.
Shame. Simple class-based React-components are joy to work with. Flat code layout, simple life-cycle, no new semantics to learn ("rules of hook"), no crufty mem-allocation.
I firmly believe that FP-seepage into web programming is one of the reasons why so many web apps are so slow and feel sluggish, jittery.
The great downfall of hooks, IMO, is that they allow you to create components that look clean and legible, but act unpredictably because all of your state updates are triggered by variable reference changes. The idea is that this makes your state updates happen automagically so you don't have to think about them, but this is a classic example of an abstraction that works until it doesn't.
Redux mainstreamed the concept of reference changes triggering updates, but I think this is a horrible pattern - we don't even have an operator in JS for explicitly passing by reference, so you end up destructuring large objects constantly in order to change one property and create a new object reference, which is a totally inefficient alternative to calling a render method. Plus javascript developers don't generally think about the concept of passing by reference vs value anyway, in large part because the language gives us so few tools for making those choices.
As a result, there is a class of bugs where the only solution is to change the list of dependency variables for a given hook. It doesn't take a huge amount of complexity for the implications of those dependency trees to bend the mind, and the "clean" syntax of hooks comes crashing down.
I can't speak in general, but there is one thing I vaguely remember being on the React roadmap as part of the class->function switch that AFAIK never happened (at least it hadn't last time I did a lot of React, which was years into the switch): Because they were pure functions based on props, React-the-framework would have the class-based shouldComponentUpdate built into it and using function-based components everywhere would get a free performance boost.
Instead nowadays people who started with the function form don't know shouldComponentUpdate ever existed and all their React components constantly rerender.
> You’re complaining that they made changes to it half its lifetime ago after you walked away from it and now you can’t just go back to the way it was.
Wouldn't you expect jQuery to keep using the same fundamental methodology a couple of years later?
I mean, Java was the stereotype of boring enterprise language, and has certainly changed a lot in the last ten years in terms of its shift towards functional-friendly programming.
This is just blatantly untrue. The changes were definitely not overnight. Not even close. You’re still free to write React in the old way. The docs were there for half a decade.
If they had just made a different project, we’d still be talking about the same thing. You would still be complaining that things changed and you didn’t feel like bothering to learn a new thing.
So are the Java 8 changes? Java lambda functions, streams and futures look nothing at all like traditional Java methods and threads, yet you're still free to write them, but nearly every Java Stack Overflow question has a dedicated Java 8+ answer because it is so different.
> By the time Java 8 rolled around they definitely were "traditional".
Based on my experience only once CompletableFuture was added to Java did the Future interface really start getting used in mass. Before that, there were other libs that implemented Future like things (Rx, Guava, Netty, etc) but they were not adopted across the board.
The transition to Java 8 was night and day! Roughly on par with the React Hooks transition.
I fully disagree. It's the exact same internal mechanisms lending themselves identically to rerender semantics and so on. They were exposed with new names and access methods, but enabled you to perform virtually the same component update logics, except with a few antipatterns made more difficult. HOWEVER it is also fully backwards compatible, you can run these old versions.
So, what stayed the same?
* Could still use classes
* Still had the same props & state semantics
* Components still could own state and receive props
* Some renamed code paths were used, a couple of the "componentShouldRender" style ones were dropped to prevent programmers making fatal errors
* Still wrote the same markup
* Still could use the same libraries
I never really understand this complaint; React achieved gold standard backwards compat. Either that or my 2016 era tools building in 2023 on the newest React with old ass libraries would've caused a lot more pain points!
I'm not sure I agree with this. It's "different" in that you don't need to learn the intricacies of some new data loading and state management library (we've seen _so many_ of these over the years!). But the concepts themselves are much closer to "just plain React".
Minor correction -- It seems like the page you link to has two sections: Legacy APIs and Deprecated APIs. Class components are not deprecated; instead, they are in the legacy section. The only thing that is listed as deprecated in the page you link to is "createFactory -- lets you create a function that produces React elements of a certain type."
Reminds me of a React V11 codebase at work. It is bad enough that I always include it as a heads up during our scoping, as in: "double your estimates because the version of React is so old"
New docs don't tell you how to get a minimal start anymore. You MUST fully commit to a create-react-app flow or similar, or they vaguely point you in the direction of Babel without explicit direction.
Ah, I guess you're referring to how they're pushing frameworks over bundlers?
> If you want to build a new app or a new website fully with React, we recommend picking one of the React-powered frameworks popular in the community. Frameworks provide features that most apps and sites eventually need, including routing, data fetching, and generating HTML.
> Grab react and react-dom from npm, set up your custom build process with a bundler like Vite or Parcel, and add other tools as you need them for routing, static generation or server-side rendering, and more.
Sure. But search anything about React, and you'll see examples in hooks.
I don't even understand the reason why class-based is "legacy". Why are hooks inherently better? Code-reuse is a factoring concern, not a paradigm concern. And component-life-cycle bugs are now replaced with nearly impossible to understand callback stacktraces.
> I don't think many would agree to this but I'd argue the changes are so radical that they almost should've called this new React something entirely different.
Absolutely and I've been saying the same thing for years.
IMO it was an extremely irresponsible thing to do considering React is critical infrastructure at this point. And by completely changing the methodology they made obsolete A LOT of educational content (books, tutorials, videos, etc) in an instant. I'm sure people making money of React education were very happy with this.
Don't get me wrong, I'm not against evolution. But if you're going to make such a drastic change just create a new project. Plus I wonder what other improvements/changes they could have made if they had started from scratch.
The react devs made a bunch of code migration tools, used semantic versioning, slowly deprecated old APIs over multiple versions, maintained vids and documentation. Honestly compared with some projects they handled the changes and evolution of the API extremely responsibly.
People are forcing you to use it. It's called employment.
God forbid you're a principal running into some junior engineers and they don't understand that you've forgotten more than they know, and the migration to functional components is just another part of your extended career timeline.
Also then in practice, you'll get people shrugging off their hooks get called 10 times iso 1. then maybe add useMemo everywhere just to be sure. Hmm.. still kind of weird. Maybe sprinkle in some more if-thens, that will fix it! Deep breaths..
This is the true legacy of React, and it's awful. It's not just a case of "you're doing it wrong", because even cutting edge codebases (developed in the last 1 or so) are struggling with this.
"useMemo is the solution" many will tell you. Compared to the way things are handled in Vue, useCallback and useMemo are near enough code smells for something rotting in the center of the React codebase.
If you're a principal, you should be able to keep up with modern tools. Making sure the engineers around you are as productive as possible with their current tools and processes is literally your job!
If as a principal, you are no longer able to keep up with tooling / patterns that everyone else at your company wants to use, its time to take a smaller scope or time to retire.
The job, including mandates (if any are needed) is to empower the people you work with, not to stifle them.
Does anyone seriously expect nothing to change and improve for 30 years, or however long their career is? Not just in software, but any profession. Long gone are the days when the same plow is used for 10 generations.
From my experience its not learning something new thats a problem, but getting the organisational support to push a major change through
Nobody is talking about that. Instead is about how these changes could be done without creating so much confusion in the community. In fact people embrace evolution of these frameworks but with clear changes in methodology, labeled as such and so on.
Is it really that much of a crisis to have the "0 React in 2023 experience ... don't even know the modern hello world" when one can just spend some time on their (excellent) documentation site and get back up to speed?
This is such a common problem these days. I have almost 15 years of experience with another framework, but the latest iteration is almost a complete re-write and most of what I knew in the past isn't that helpful. To say I have "x" years of experience doesn't really acknowledge my current level of understanding.
the core concepts are the same. the implementation details have changed, but I think it's a stretch to call it a radical change. you could probably learn how to convert a component from class -> functional in a few hours.
This is a kind of career violence intentional radical constant change such that experience doesn't matter maybe those of us pushed out of industry over react should hit meta with a lawsuit.
I can't tell - is this satire? Good faithing it - this could only be (partially) valid if the old ways didn't work, which they still do. If you've been pushed out, you haven't been pushed out of the industry because of the change.
I wanted to like React so bad. I tried. I loved JSX and really appreciated the way you could reuse components. That was all very cool, and I was initially quite enthusiastic about it. But for whatever reason, I just could not figure out state management/hooks. Drove me crazy. It just always felt so unnecessarily complicated compared to other languages and frameworks I've used (even vanilla JS). Now, don't get me wrong: I fully accept the blame here. I am mostly self-taught (and not even the best 'student' in that context, haha) so I'm sure I just lack the overall knowledge base/big-picture understanding to really appreciate what they've done here. I hope I'll give it another shot one day, and perhaps with fresh eyes (and maybe with the help of a patient tutor), it will all 'click'!
This is the best explanation for both async/await and hooks that I've ever heard, thank you!
It also shows that although there might be some learning investment required to use the more modern version of both, it's well worth the effort. I can't imagine going back to callback-riddled javascript
what do you mean async/await "replaced callbacks"? Async/await "replaced" Promises, specifically then/catch chaining. Turns out Promises can be syntactically-sugared to imperative try/catch blocks.
I’ll be more pedantic than that! Await is more akin to yield, the fact that it’s specific to promise resolution is a specialization of the more general function body suspension used by generators, with an extra specialization for event loop scheduling. And async just means you’re returning a promise no matter how your function exits.
hah, good point. Just wanted to point out that callbacks and async/await are different things, and callbacks are still the preferred way to customize behavior.
Hooks use a different paradigm, which is a solution to a problem you encounter when doing functional programming, which is persistence and side effects. The whole of React is to build a tree of objects that will be rendered into a HTML page. The previous class-based architecture made it easy to store state and add side effects to this tree, by using properties and methods. But pure functional programming makes these awkward as functions are transient, only transforming parameters into return values.
I don't know exactly how – never had the time to properly research it – but, my current guess is that the hooks code taps into the scheduler/dispatcher – which handles the execution of the function representing the component – and stores value and logic somewhere. It uses the order of these calls as keys – you don't have to specify them – and provides the stored values as return values of the call of the hooks functions.
Hooks are escape hatches from the functional paradigm of React's components. You are always providing new values, and it decides when to store the updated version – mostly based on the deps array. You then get back what you stored. On the surface, it's still basically functional, but the actual logic is not. It's more like a repository of code and values.
One view of Hooks is that they are monadic or at least Monad-like and the deps arrays are a crude (reversed) notation for algebraic side effects. ("Reversed" because they declare which dependencies have side effects more than they declare which side effects the hooks themselves produce.)
It's still so very functional programming-inspired, even if the execution engine (scheduler/dispatcher) isn't that much like the Monad runtimes of most functional programming languages and the various Hook "monads" don't get captured in even the return type of functions (much less the parameter types) and get elided away. (It could be more "traditionally JS monadic" if it [ab]used async/await syntax and needed some fancy return type, even though the concepts for hooks don't involve Promises [or Futures, being the slightly more common FP Monad name]. Though also, from Typescript patch notes, I've heard React is exploring [ab]using Promises for something like that in the near-ish future.)
Monadic bindings needing to be in-order, just the like "Hook rules", isn't even that strange from an FP perspective: there can be a big difference in which of two Promises is awaited first. There can be a big difference in which IO binding executes first (you don't want to input something before the prompt of what to input is printed).
All hooks are based on useReducer. Whenever a component is rendered React sets a global (!) variable for the current component. They didn't even bother to have the component be a parameter into the hook to get rid of the global variable. No, it must be pretentious and claim to be something it isn't. The global variable stores a linked list with the hook data. The calling order of your hooks matters.
Don't blame yourself. Software engineering tools are supposed to serve the programmer, not the other way around. If a tool is too hard to use, then you're using the wrong tool. Tools should serve the developer. I would recommend plain old javascript with a light wrapper on top, like jquery. I know i'll get downvoted for this but a lot of "modern" javascript frameworks don't properly abstract the underlying layer properly (read Joel spolsky's article on leaky abstractions) and this results in a lot of problems. Furthermore, they optimize for the wrong thing: writing code. Most engineers spend 95% of their day reading code and that's a lot harder than writing code.
it's true, React, Angular and other popular heavy frameworks aren't designed to serve the programmer, they're designed to serve the organization that owns the codebase by making turnover easier. They force a specific approach and layout new hires can be familiar with, regardless of if it's even a good idea for the application at hand.
There are certainly benefits from doing things in new ways, but a lot of the time things swing too far in the opposite direction, and become of a form of “IQ signalling” for smart developers.
It isn’t only front-end developers who are prone to this: 20 years ago, before FP became a mainstream thing, being able to do pointer arithmetic was seen as the differentiator between a “smart programmer” and a “bad programmer” (https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guid...).
Was React great and fun to work with? Yes, but then Redux came along and made something simple into something stilted. Our team used Mobx instead, which was simpler IIRC.
Similarly it’s been a couple of years, but I remember React Hooks being a bit complicated for the value we got out of them.
Ultimately, it’s hard to tell if something is an improvement, or a time suck to allow the elites to stand out. I stopped playing the game and stepped away from front-end development, as have many of my experienced colleagues.
I’m assuming things have settled as Big Tech focusses on profitability rather than funding an endless parade of frameworks, and the IQ-signalling will become less prevalent as generative AI competes with the brainiacs. When that happens, I’ll dip my toes back in the world of front-end development.
Hooks are half of an object/class system (implemented on top of a language that already had a whole one—arguably, two, from a DX perspective, though they're one under-the-hood) with non-standard and hard-to-read declaration syntax and bizarre behavior (FIFO-by-declaration-order property access and method invocation). It's not your fault you're having trouble with them, they're a weird boondoggle.
That’s the magic of react. The problem is no longer manually managing transitions between state but state itself.
That’s why state management is so critical in the react ecosystem.
Further, react has delegated two key features to userland: side effect and state management.
Personally, I don’t want react to solve either of these problems because it’ll just turn into the disaster that is react server components: feature development driven by corporate interests (eg vercel).
If this was actually how it worked, I'd have much less problem with react. What I mean, specifically, is that not all function dependencies are explicit. This makes it look like the state is passed into some function. And then the view is returned, depending only on state. In reality, half the state is passed in (as in the argument to a function call), and half comes out of some mysterious hook storage structure. If the state was really a function argument, you could easily inspect the whole state in a debugger. Instead of... I'm not sure how you'd actually do that.
This brings up other questions too. Is the state on the client? How does one reconcile the server state and the client state. Is the client state a subset of server state? Is the client state a tree matching the view tree? Does the state contain only the UI data to be rendered or is it all app state.
> it’ll just turn into the disaster that is react server components: feature development driven by corporate interests (eg vercel)
if you've followed along with the react team's discussions on server components, it is very clear that vercel implemented the react team's vision and less so the other way around.
as someone who has been using them extensively, I understand why. they're delightful.
vercel does control next.js which is the only framework to completely implement RSC, but as other frameworks catch up, RSC will have a wider surface area.
Hardly a wild take though, is it? You're in the context of "I am mostly self-taught (and not even the best 'student' in that context, haha) so I'm sure I just lack the overall knowledge base/big-picture understanding" and you come in and say view = func(state).
Here's how the React docs introduce it:
"React is a JavaScript library for rendering user interfaces (UI). UI is built from small units like buttons, text, and images. React lets you combine them into reusable, nestable components."
Hooks are complicated, but state/props is just right. Both enables you to enforce boundary and make contained components. If props and state are mixed / diluted, the component won't know when to do re-render and there'll be too many things to track, and there'll be many classic issues such as cyclic dependency and sluggish performance of two-way data binding.
1) React has no state management - approach it not from what it should be, but what it is - a tree of components that just render their props and where each component has some internal state.
2) Components have behavior. In Class based components they were implemented as methods. Simple enough, classes have methods. If you think about an iteration of rendering the ui tree, it goes down the tree and calls the mount method for each component in the ui. With hooks, instead of calling a method on an instance, it's implemented as an inner function of a component that is also a function instead of a class. Instead of explicitly calling the mount method on a class instance, calling a function that's a component automatically runs it's inner mount method. The way that it knows the which inner function is a lifecycle hook is because you import something like 'useEffect' from the react library. And that global useEffect function knows the current component because the renderer sets it as it's going down the ui tree. Hooks are better because they can be written as arrow functions (more concise, cleaner), and because you're calling a framework function, that function can have more complex behavior like how useEffect can track when to update because it's being passed in an instance of something like an internal state variable.
I've been using Preact signals, which are also usable in React (though admittedly I haven't tried to use them). I've found them to be much more pleasant than useState (though I reflexively continue to use useState). I also use a pretty lazy pattern where I allow large portions of an application to rerender when state changes (implicitly by letting prop changes percolate through). For simple apps this works really well, and for complex apps it still works. Like I have an app with 200Mb of rendered DOM nodes that get rerendered from the root when anything changes, and it's totally fine. I wouldn't ship that app widely, but for internal use it's 100% fine.
I’d be interested to know if NakedJSX works for you. I released it about 6 hours ago and I'm looking for feedback. It allows you to use JSX (without React) to generate static HTML, and also to create DOM nodes in client JavaScript, and without any of the client side ‘framework’ stuff of React. You have full control over what happens when.
I think there's a niche for libraries that allow you to update the DOM declaratively without any requirements on how you manage state. My understanding is that React looks at props / hooks in order to diff the state of your app and selectively recompute the virtual DOM. An alternative is to naively recompute the entire virtual DOM. I think this is how Mithril.js does it? It may be less efficient for large apps but it lets you manage state however you like.
As someone who worked with jQuery (15 years ago), then Backbone.js, then Angular 1, then React (for the last 6 years or so), I honestly feel like React is here to stay. It solved all the pain points I had with the previous frameworks when working on complex and massive code base. I have a level of productivity I never achieved before. I never have to check the docs, I can't remember last time I thought to myself "why is this not working" or "how am I going to do that" or "what's the syntax/arguments of X". It is amazingly simple, intuitive and powerful. Most of the time I'm just reusing components I coded years ago, gluing them together to develop a new app that would have taken me days with the previous frameworks.
> As someone who worked with jQuery (15 years ago), then Backbone.js, then Angular 1, then React (for the last 6 years or so), I honestly feel like React is here to stay.
That sentence didn't end how I expected it to. Personally - coming from a similar (jQuery -> Knockout > Backbone > Ember > Angular 1 > React > Svelte) background - I feel React has gone the same route as the others - rose quicky, dominated, and will never go away, but no longer has any influence. The same will happen to Svelte in future.
React still has some tricks up it’s sleeve with great potential that are (often) missing in comparable frameworks. Error boundaries, async (server) components, suspense, portals, dynamically imported components, concurrent mode. Just a shame it takes/took forever for suspense to resolve.
Whatever one feels today about React, there is no doubt that it has given functional and declarative programming an important light.
Not in the sense that React itself is functional or declarative (it isn't albeit its roots are in Ocaml), but the style of programming it introduced to many millions of web developers made a sizeable chunk of them interested in fp and many of those percolated to strictly typed FP in TS, Elm or Haskell.
Pretty much every major fp language has tried to implement their own declarative UI after React's success, be it for terminal applications or native development.
I think these two are React's biggest lasting contributions. Describing UI in a declarative way, and introducing many functional programming concepts to the world's JS devs.
I myself fell in love with functional programming in part because of many of the concepts I was introduced to by the likes of Dan Abramov and company.
It led me down paths of research I wouldn't have known to go down, all the way back to the dawn of computer programming.
> React's biggest lasting contributions. Describing UI in a declarative way
I feel that AngularJS (v1) did that years before React, and maybe even other MVC frameworks before that.
I can't think of anything React brought in that earlier frameworks didn't already have in a form or another. Maybe hooks? Arguably the worst and least performant part of React.
It only popularized "HTML-in-JS" but that has always been possible via strings or file imports. Even template pre-compilation was part of Backbone or Ember (I don't remember which)
> I feel that AngularJS (v1) did that years before React, and maybe even other MVC frameworks before that.
Angular markup lives in templates which are used to generate and update the UI, while React markup lives in expressions which evaluate to values. This is a subtle but key difference. I would argue React isn't even an MVC framework (though it sorta pretended to be one for a while)
> I can't think of anything React brought in that earlier frameworks didn't already have in a form or another. Maybe hooks? Arguably the worst and least performant part of React.
The virtual DOM existed only in a library or two that you had to build around, before React made it into a useable framework. The whole "automatically figure out minimal DOM changes", especially things like reusing existing <input> elements so the user input doesn't vanish or the element lose focus, were pretty much brand-new when it came out.
> but the style of programming it introduced to many millions of web developers made a sizeable chunk of them interested in fp
Why would that be? React is not functional, and the style of programming has nothing to do with functional programming. It is fundamentally inconsistent with functional programming.
> Not in the sense that React itself is functional or declarative (it isn't albeit its roots are in Ocaml)
At the beginning of React there were two different components: class-based and pure functional components. Pure functional components rendering has always depended _uniquely_ on its props. No surprises. This introduced a very large number of developers to indeed a declarative/functional style of programming which only depended on the inputs in an era when components were written with local state. Several libraries like Redux, which was Elm-inspired, further introduced millions of developers of combining a declarative/functional/reactive paradigm with handling state without mutations but messages.
Context, then hooks and other features broke this paradigm, whatever is the final result does not depend anymore uniquely on the inputs. React team believes the net result is positive.
I myself with others who commented in this thread and plenty of people I know where introduced to this style of programming with React and then migrated to more strict libraries in the TypeScript ecosystem or other languages such as PureScript, Scala, Elm, Haskell, etc.
Indeed. I would add as well that React (for me at least) went a long way towards erasing the difference between "backend" and "frontend" development. When I was a pup, they were very different things and a "frontend" developer meant basically someone who was really good at CSS and HTML and new all the magic incantations you had to do to create a nice UI with them. There were of course precursors such as AngularJS (and others) but React was really the first one for me where I could see frontend dev as just learning another framework the same as I would learn a backend framework.
I think React really was revolutionary when your choices were jQuery, Backbone, or even Angular 1. I remember trying to convince my team that React was the next best thing when it first came out. Skepticism was everywhere — especially around JSX. So we compromised and wrote our components with CoffeeScript…
The sheer number of flux frameworks were a testament to how underserved the state model was at the time. And without consistent support for async/await to make Promises work well in an app, data fetching and state was the worst part of React.
I’ve always despised Redux and the circus that came with thunk generators. MobX made things a little bit easier. And Baobab was a fun concept to bring Clojure-style cursors to JavaScript. It wasn’t until React shipped the context API and hooks that I felt the problem of, “how do I get this state from up here to down there?” was truly solved.
Personally, I’ve wished I could quit React for something like native Web components, but I feel like I’d be back at square one with state management and stringly-typed templates. Maybe Lit-HTML will get there one day!
Out of interest why did you despise Redux and Redux Thunk? Imo Redux did solve the problem of state management and I always thought it was quite an elegant solution personally.
Hooks and the context API are just different ways to manage state (and many would argue better). Do you disagree?
As a backend developer who didn't 'get' web development for many years. Learning react changed all of it. React was revolutionary, and just clicked for me. Combine this with frameworks like Material UI, Patternfly and many others and its almost like you have some super power. These days I can build fairly big sites with lots of stateful components quickly.
Most of my use cases is to build internal tools. But the pace with which once build things in react and its over intuitiveness just makes it special.
React is one framework which Im sure will be available for long time to come!
As someone who started in front-end and was deluged with 2000s conventional wisdom like "don't use inline styles" and "keep scripts separate from your CSS and HTML markup", React made absolutely no sense.
Even if people understand this at a conscious level, it's rarely explained:
> and "keep scripts separate from your CSS and HTML markup"
was for documents, not interactive applications, with the goal being that a document could be reformatted through CSS for multiple different displays. The earliest example I can recall was web vs print (as in, in the browser go File -> Print; you can specific different CSS rules so the page prints differently than it shows in the browser). Screen size / mobile displays are other examples that came later.
React on the other hand is great for interactive applications, which have always worked component-style - a checkbox or a dropdown in a native GUI would be used multiple times and knows how to style itself, for example, which is the same as what a React checkbox or dropdown would do.
> "don't use inline styles"
This rule was broken simply because there wasn't a better way to do the component packaging at the time. Nowadays we have CSS Modules, which separates them again.
Agreed. There's a "before I knew React" and "After I knew React" bifurcation of my career.
Before, I could call myself a "full stack dev" because I could cobble together a site with JS, but it wasn't pretty. It didn't follow any real conventions, was a nightmare to maintain, forget about testing, etc.
After learning React, I actually can design, and structure the code in a logical way. Testing is a lot simpler, code reuse makes sense... it created a mental framework on which I could translate my ideas into usable code that pattern matched to how I was used to building code for the backend.
I will never feel like I'm a "frontend dev", but I don't need to be. I can take an idea, and turn it into a functioning service, and isn't that all we're here to do anyway?
I have been using React for almost those 10 years. When I first started out, I was writing Java for Android. I then got a contract position writing AngularJS 1.2. A couple years later, Angular 2 would be released but by then I was already beginning to write small React apps. I also made a small app with React Native for an audio company. By 2016 I was working at a popular Fortune 100 company on the first team to migrate their existing JSPs to React. By the time I left that place, React Hooks were in beta and gaining steam. I was lucky enough to work with a Facebook Alumni who hated React, so we used Vue. It felt like a more opinionated React in some cases, but I really enjoyed the experience. Now I'm back to React and a lot of the same problems exist. Some things are just hard or extremely tedious to do. Some places rely heavily on external libraries which cause so much bloat to the system it can feel slow (even when it's not). Most places I have been to are extremely opinionated about how their app is built, despite it being the same thing (for example, there are 20 different ways to build an e-commerce site). But the places I have enjoyed the most had a hackerish culture, so people weren't insanely opinionated so long as you got the job done, which I feel like React is great for. I have unfortunately not used NextJS, but I have used Nuxt which has been wonderful. I'm semi in between jobs right now and have been looking at potential offerings, and I haven't seen a huge need for these frameworks yet. If NextJS is anything like Nuxt, I think I'd be happy to work in them. But I may also look for the places that offer a completely new experience.
SolidJS? It uses Signals in its Reactivity system and there's no virtual DOM. It has some syntax similarities to React making it easier to transition. It uses JSX and is quite performant.
I love Solid. In the last month or so I went from curious to fairly certain I’d prefer to work with it over React.
I’d used it before to trial it and explore differences, but never actually built something. I used it with XState (state charts) to build a version of Minesweeper which uses the receptionist pattern to orchestrate actors, which was pleasantly unnecessary, and I really loved it.
Although I have around 8 years of experience with React, Solid somehow made the process easier in some regards. React — despite being excellent in many ways — has a few sneaky foot guns that I still manage to wander into when trying new tools and patterns. Solid on the other hand was quite friendly. Ironing out anticipated performance issues was mostly an idea and never became necessary. In React I did need to tidy up some redundant renders and fix state synchronization due to out of sync effects.
I’m currently job searching and totally wouldn’t hesitate to work with a team that uses Solid. But, React is good too. At the end of the day I just love making things people enjoy using.
10 years and we are still building custom forms from the same primitive building blocks.
And with react having to fudge with the state of DOM input components, it's been a messy ride.
And yet, the idea of describing your UI and have a library figure out what needs to be repainted has been liberating.
React certainly wasn't the first, but it certainly was the most elegant one at the time.
I wish React would split up and go back to the roots: Have it deal with rendering - and nothing else.
Have optional companion projects that deal with the various forms of state and side-fx.
I've been maintaining a project for 4 years now (~40k downloads/mo on NPM, 400+ stars) that is simply glue code between a React form management library and a React UI library. It was really hard to get right, still isn't perfect, and over the years has required several major upgrades to keep up with changes in all three. Luckily, I have very good unit tests and snapshots that ensure upgrades don't break things. You'd think it would be easier, but it isn't.
I really wish React would just own the low level forms stuff and get rid of the need for a 3rd party form management library. That said, because it is frontend JS, there are 1000 different ways to bike shed this problem and because it is form stuff, there is no one solution that fits all use cases.
React is a text-book example of what a well-designed component model can do to a development cycle: a literal 5-20x productivity boost compared to the old vanilla JavaScript with jQuery and manual HTML manipulation.
I was somewhat skeptical in the early days of React, but once static websites with rehydration became a thing, I was fully in. So much power.
See the web app. It is a more productive style of coding. Simple, and no need to deal with hooks and useState and useContext and none of that nonsense.
I've read the web app and it seems to me it is just https://backbonejs.org/ re-written in Typescript and allows JSX.
I'm very certain Typescript and JSX will have improved the DX for Backbone like apps, but it doesn't address all of the other issues that teams had with Backbone.
e.g. Cyclical event propagation, state stored in the DOM (i.e. appendChild is error prone in large multi-person code bases), etc.
There is no two-way data binding in use here, so you're wrong.
The style used is MVC. Do you think MVC is not suitable for multi-person teams? If so how do you explain MVC in Cocoa, ASP.NET Core, JSP and JSF, Ruby on Rails, and Django (Python)? They are all based on MVC.
> There is no two-way data binding in use here, so you're wrong.
Cyclical data bindings and two-way data bindings are fundamentally different issues. Not knowing the difference makes it pretty clear you haven’t lived through a codebase that had these types of issues.
MVC seems great in sprit and breaks down at the first real interactive, stateful usecases.
> Do you think MVC is not suitable for multi-person teams? If so how do you explain MVC in …
Correct, I do not find MVC suitable for multi-person teams. You won’t believe me, but it is an incomplete abstraction that was previously relied on but since React and also modern video game engines it is no longer in favor.
Why is it still used by all those legacy frameworks? Because, frankly, they are old and haven’t evolved.
Apple has moved on from Cocoa to SwiftUI. Java devs have all but moved on from JSP (goodness those days were terrible). Rails for all its awesomeness has been stuck for years not able to move past itself and typically now paired with React or Vue.
MVC was a good stepping stone, but now we have learned and we are moving on!
Sorry none of this makes any sense to me. You can't have cyclical data binding when you only have 1-way data binding. MVC is absolutely perfect for stateful use cases. In fact, it is React that suffers a total breakdown in stateful use cases. If your component is stateful and you need to update props then the recommendation is to set and change a key, which replaces the component with a new instance. This of course eliminates any benefit that React provides.
Sorry your last attempt failed. If you have been following React discussions on HN you know there's massive criticism about hooks. MVC is still the predominant pattern and for very good reason. Backbone.js is not relevant for this discussion.
Looks like MVC/MVVC, something that has been available to do in JS since long time ago (Backbone.js was a popular option for doing a modified version of this). Or I'm missing something obvious. Care to explain a bit more in detail?
No, Backbone.js doesn't do 2-way data binding, although some certainly made it do that. But it doesn't by default, it has a 1-way data binding (the UI updates when the model changes, but doesn't update the model automatically when the UI changes).
> Some people mistakenly think MVC implies 2-way data binding. It does not.
What? Who does that? I certainly didn't and I haven't heard anyone in my +decade of web development.
Famously, a Facebook engineer declare on stage that MVC doesn't scale. Later it turned out that she was talking about one specific implementation of MVC that used 2-way data binding. She assumed that 2-way data binding is part and parcel of MVC, because that's all she had seen.
10 years, and yet any discussion on this site about front-end development will be filled with people complaining about how front-end development practices change too quickly.
React development has had multiple major changes over that time span, as far as what's culturally allowed & encountered in the wild (if not what's technically possible). Just-functions, classes-and-functions mixed as appropriate, redux becoming a nigh-standard, the HOF invasion, hooks, and classes becoming deprecated.
To be fair, React itself has changed in fundamental ways multiple times throughout that period. And it's not like React is the only thing you need to worry about when building a React app: there's a whole ecosystem of tooling and libraries that you rely on which are constantly moving.
What common, popular and highly used technology hasn't radically changed in the last decade?
Back in 2015, $JOB was evaluating upgrading Java 6 to Java 7 or 8. What is now? 20?
I last touched php in 2012, which was 5.4 or 5.5 I think. People were still arguing that Laravel couldn't replace CodeIgnitor, or that we should stick with Symphony or Zend.
Change is the only constant. In that respect, React has been relatively sane.
As you know, Java and PHP are languages. React is just a framework, and by design not a particularly robust one on its own. It just provides a front end, everything else has to be plugged in separately, learned, maintained, and ultimately cast aside and forgotten separately.
If you're a React developer, you'll have noticed that Javascript itself has changed a lot in ten years. The state management library your company uses has probably changed too. Compared to ten years ago, you're now writing fully-typed JS with Typescript. The additional libraries for authentication and persistence, and so on, have all changed as well. You may be using a graph-based database now. You may have a different JS runtime on the server. All of your tooling has probably changed, as has your IDE.
Whether React itself has or has not changed more than other frameworks, I can't say. But, I'd bet the stack used by the average front end developer has. Please recall that the original comment we're both talking about was referring to complaints about how much the front end has changed, with React only being the context of the comment, and not the sole cause of the complaint.
> Ok then, what about the Spring .xml to .java migration? What about the Struts -> Struts2 -> SpringMVC -> SpringWebapp migrations.
When I started my first programming job 14 years ago xml was already not recommended and SpringMVC was already the way of doing things. So that's quite a bit stabler and slower than React.
Just as much as I had to rewrite anything in React. We stayed with Redux with Context became available. We stayed with classes when Hooks was released.
I don’t agree with that blanket statement, though I do agree that it (and libraries/frameworks like it) have played a significant role in bloating the web. Perhaps even bloating development tooling in the JS ecosystem.
At the same time, my capabilities with web applications have skyrocketed in the last ten years and I wouldn’t credit it strictly to my experience. These tools aren’t only used because they’re relatively accessible; they’re genuinely capable and powerful, and when used well, allow remarkably fast development and iteration on products with real value.
I think that’s better than the bad parts. Also, a lot of what’s bad about the web today (for me at least) has virtually nothing to do with the tools we use to develop. It’s that our attention has been commoditized, and that market has eroded a vast portion of what made the web exciting.
I don’t think direct DOM manipulation was ever a problem, if done thoughtfully.
If keeping track of state is so hard that requires a library to render it, perhaps you have too much state for a single view. It’s ultimately a UI/UX design problem, as it will be hard on your users as well.
I find the way they mix markup with code distasteful, and lots more.
> By removing these arbitrary constraints htmx completes HTML as a hypertext
I agree, this is interesting. I even agree, htmx is probably a polyfill waiting for the browser standards to catch up.
That said, trying to make a markup language smart is a losing battle in the long-term. It makes simple things like `if` and `while` difficult. Markup also really struggles with time / interactivity.
e.g. What should be displayed when a form is invalid? https://htmx.org/docs/#validation-example is just not ergonomic even for a simple case, let alone complex validations that interact with other fields, are async, etc.
I get a allure of wanting "only a markup language", however, it just isn't enough to be competitive for 95% of web development these days. In a different response you say "if you're building the next Gmail, fine use React, but you don't need React for picking between 3 colors to order a shirt". This is true, but it is fundamentally lacking the realization that no company wants to end their feature set at 3 colors for a shirt. They "want" to build a foundation quickly, but then enhance it to be able to custom create the shirt for exactly your body sizes and allow interactive movement of the "logo" or "graphic" anywhere on the shirt. They want the validation to ensure the shirt can be printed, and they want to ensure their logistics network is dynamically updating the order history for live tracking of the package.
To get there, the best thing to do is to use React (or similar) even when it is "just 3 colors".
This is the premature optimization our industry suffers from.
If/when you get a few million users, then you worry about scaling your backend with microservices, crazy DBs, serverless, whatever. Until then (vast majority of business), LAMP is fine.
If/when you need 20 checkboxes/drop-downs (again, there are very few situations where this is reasonable to the user, the mental load is non-trivial, consider splitting the view and adding a “next step” or something) than you consider a framework devised to render the whole of Facebook, a site with way more views and features than the most sites would ever dream of.
It's less keeping track of state is hard and more keeping state in a medium that isn't suitable for it (the DOM). The argument of too much state in a single view is nil by what applications are built nowadays (and also expected). Obviously it was already possible without the rise of declarative rendering frameworks but it made it more accessible to the majority of developers and thus raising the bar.
If you do however find the way markup and code is mixed feels distateful, I'd suggest to not look at any templating engine in the last 20 years because that's what most of them already did.
If you’re building a Gmail competitor, by all means, go with React, build your own solution, whatever. If you need to choose the color of a shirt with 3 sizes, perhaps it’s an overkill.
The concept of the Virtual DOM is a means to an end to achieve declarative UI. It being "fast" is a common myth that spread in React community. Fast compared to what?
I understand some comments here are saying that they feel React is here to stay. I have no basis to judge that, but putting that side, a question: what is it about frontend web development that seems to lend itself to neverending development of new frameworks or ways of building apps? I'm genuinely curious. Is there something inherent in developing web apps that just isn't quite solved, some way in which each new framework doesn't quite solve the problems (whatever those are)? Or is it just that the web (unlike mobile) is so open and there's so much development interest that this leads to endless efforts to improve on what came before leading to new frameworks all the time? Appreciate any thoughts on this!
Coming from the backend, I feel the exact opposite. For any kind of frontend development you have a choice of ~3 clients, one programming language, a handful of frameworks, 2-3 of which have any real traction.
Compare that to literally hundreds of programming languages that can run server side code, dozens of database engines, servers, all kinds of operating systems, hosting platforms...the web of backend tech is pretty much endless, and growing every day.
You are correct, there have been changes on the back-end as well: containers and Kubernetes vs serverless. The endless tension between microservices and monoliths. Multiple IaC options. Onprem vs cloud (which cloud?), and associated cycles of disillusionment.
The difference may be that once a particular back-end approach/architecture/design is adopted by a dev shop it remains stable over multiple projects. I’ve seen this in both consulting and in LOB roles. Because of this, I can hire a competent .NET developer and be confident that I can get them to be productive relatively quickly, since the foundation on which we write our code is stable, and I can invest in enhancing the developer experience to support them. In fact, an explicit criterion for every project in my teams is that we make it easy enough for any competent C#
developer to ideally be able to open a small, but meaningful PR by the end of their first day on a project (if needed, I don’t treat it as a retention gate or anything!). They do have to adapt to our infrastructure and our ways of working, they don’t need to relearn the fundamentals of how to produce code.
Whereas every time a new front-end project starts, there’s a near-compulsion to use the latest and greatest techniques. Everyone has to catch up, because of their previous experience being somewhat redundant. No one can invest in improving things for other developers, because they don’t have the time, and because any investment would be wasted, since it would be redundant beyond the current project (or two, if we’re lucky).
I can’t really hire an Angular developer for a React project that starts tomorrow, and expect them to be reasonably productive immediately, despite them being competent in Typescript, CSS, Node etc. Heck, I wouldn’t even be able to hire a React developer who last did it 5 years ago, and expect them to be immediately productive.
Regarding the last paragraph, I think an experienced developer can jump to new frameworks relatively quickly. They won’t be putting out PRs on day one, but can certainly do so in a week or two with a new framework. If your web fundamentals are strong, one can get through the docs for a new framework in a few days, then spend a couple of days looking at GitHub repos that use the framework in question to suss out best practice patterns of code organisation and you’d be in a good position.
It’s odd to me that frontend dev jobs ask for experience with specific frameworks, since most of the popular ones share core fundamentals a lot of the times. It’s no different than going to a new backend role to work on a large existing codebase. The codebase will have its own homegrown patterns and concepts to get familiar with anyway, how is this any different?
I was referring to greenfields projects, but the problem is even more acute for the maintenance problem you outline. You have a portfolio of front end projects: each one would involve learning whatever quirks the framework and implementation were used (by necessity). A company with a reasonably consistent back-end architecture, project structures and coding practices would have an easier time onboarding maintenance developers, as long as each project was done with some kind of eye to maintainability.
This whole discussion is concerning. So can somebody please point me to what is considered the modern React way? Educational resources, Tutorials, Docs please? Or is this modern way based on Beta documents?
That would be a good place to start. Node.js is the defacto standard for JS based tooling, along with npm (node package manager) as a public module repository. There has been some evolution in the space.
If starting a project, I'd probably start with Parcel.js [1] and from there use typescript/tsx instead of JS as a core. But that's just me. I also tend to do Redux the "hard way" closer to the original structure instead of redux-toolkit, as I find it's more overhead to learn initially but avoids a lot of additional complexity over time.
We'd _like_ everyone who is writing any kind of Redux code to write that using Redux Toolkit, and we teach RTK as the default approach for using Redux. FWIW, we've had plenty of beginners tell us they were able to get started and be productive after reading through the "Essentials" tutorial in our docs, which walks folks through how to use RTK to build apps.
I just find that the original reducer pattern(s) are easier to deal with in practice, especially when a project is slightly larger. It's often better imho, to understand the original patterns and some of the RTK approaches kind of muddy that understanding.
I'm not saying that RTK is necessarily bad, but feel that when you're using some of those kinds of slices, or merging the constraints of the actions, mutations and the abstractions, it's harder to reason with. You aren't thinking about state as a whole, or often even your fragment.
I'll sometimes mix a few things as well... The React features for provider/consumer, etc are sometimes easier to deal with as well. YMMV based on your own needs.
Hmm. I'm a bit surprised to hear you say that writing reducers "by hand" is simpler than with RTK.
Per the docs examples (like https://redux.js.org/usage/migrating-to-modern-redux#reducer... ), hand-written reducers normally involved `switch` statements and lots of immutable updates with object spreads. Those were normally accompanied with a bunch of separate action type string constants and action creator functions.
With RTK and `createSlice`, the reducers themselves are much simpler: simple functions with "mutating" update syntax (which uses Immer to turn those into immutable updates), and the action creators get generated for free:
That's a lot less code to write, much simpler and shorter to read, _and_ it eliminates accidental mutations.
You're still writing a "slice reducer" at a time, so it's the exact same amount of state to consider (ie, a "posts reducer" that manages `rootState.posts`.
Also note that we do have a "Fundamentals" docs tutorial that teaches the underlying concepts _without_ any abstractions, but then shows how RTK simplifies those patterns:
I've seen the examples and worked with RTK.. I still prefer the "hard" way. And I'm not the only one.
edit: I tend to find the separation of a more basic reducer, even with the switch, easier to deal with in practice. Not to mention, that action creators that are separate are easier to integrate with thunks and async data fetching IMO. The base library for Redux does very little. And if I'm going to stray from that, I'm more inclined to use something based on Proxies that feels more natural to use in practice than RTK.
React is really good for helping create giant SPA apps for the web. Unfortunately 99% of things using react aren't or shouldn't be SPA apps and now otherwise trivial applications are orders of magnitude more complex in their implementation and much heavier on bandwidth than necessary.
I'd say it is less about being a mess and more about the fact that there are 1000 projects that do state management in totally different ways and it is nearly impossible to figure out which one to use. Even if you pick one, you don't find out that it has some critical bug until you're half way through your project and it is too late to swap it out. So, you end up coming up with some hacky workaround that creates a lot of brittle code and breaks every time you upgrade some other non-related component of your application.
I once tried to learn what you would call "proper React", only for some Googler to tell me I wasn't even using React. Despite the fact I was using it back when hooks weren't a thing, and I had built multiple apps with it. There are many things I can stand in a community, but gatekeeping is not one of them.
I don't think React will be replaced for a very long time. The only library that has somewhat similar adoption rates to early React is Vue. I personally prefer Vue over React and I use it at work. But I would be happy using React as well if the choice was given to me. Vue3 + Composition API just makes sense to me.
Vue 3 + pinia is simply an amazing experience. Nothing is shoved down your throat
I tried getting back to React but Vue makes so much more sense. Feels like in the old days because all you do is write your code instead of dealing with a library and its ways.
To de-throne React, React would have to stop de-throning itself.
I do think the future of DOM based diffing is no longer going to use a Virtual DOM. Svelte has shown the way. It just has to be moved into React (or a React successor).
I also think the future of Components is to use async/await more. Where each await point is assigned a fallback component e.g. <Loading /> or something.
React also needs to figure out Hooks a bit better, and see if there is a missing language feature that can be pushed to simplify that concept.
If something (including React) is able to do those three things, while also keeping/improving the React DX (markup and logic together, uni-directional dataflow, hook like annotations that can interoperate with each other), it'll likely de-throne React.
Have you seen React Server Components? You mark a component as `async`, and then you `await` some Promise inside of the component to fetch data. The fallback points are declaratively defined through React Suspense. For example:
<Suspense fallback={<LoadingSkeleton />}>
<MyComponent />
</Suspense>
Where your Server Component then looks as follows:
Yes, aware. Its cool, but the ergonomics feel very much the way I felt about Node.js with callbacks.
There is a different type of delight that comes from the ergonomics on async/await. This is the big jump React Suspense also needs to make. I am not smart enough to suggest anything here tho. I just know the framework (including React) that can give me that async/await delight while using Suspense will dominate!
It'll be a long time before something comes along and dethrone react. React ecosystem is too vast and the community is large and engaged. Nothing comes closer to React atm.
Yes. Nothing excites me more than web components and moving closer back to the browser. Somehow, it feels more exciting than server components, signals, compilers, resumability, etc. etc.
I learned jQuery long ago, then how to get most of what I wanted done via document.querySelector/etc instead since it was more "lightweight", then I learned React "class components" with render() and componentWillMount() and it was a big leap forward.
The "major breaking changes" (semantic versioning wise) to move components to functions (instead of implying it's just a class with render()) and then hooks on top, it almost invalidates most of what I learned about React initially. Which is fine. The community reserves the right to grow however they want. I was just surprised when I recently revisited it. The only common concept was basically JSX and "view/render state/props + actions on events".
I don't think many would agree to this but I'd argue the changes are so radical that they almost should've called this new React something entirely different. It would help. Saying "I know React/I have React experience" is basically in need of nuance like "I have React in 2018 experience, and 0 React in 2023 experience, therefore I don't actively/actually know current React best practices or how to even do a small TODO hello world list example".