Hacker News new | past | comments | ask | show | jobs | submit login
React is 10 years old (twitter.com/dan_abramov)
190 points by ggregoire on May 30, 2023 | hide | past | favorite | 239 comments



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.

Edit: here's the video (from 10:20) https://www.youtube.com/watch?v=nYkdrAPrdcw


As a misuser on hobby projects, what is the best way to do an initial API call once the main component has mounted?

I was using useEffect, with the deps being the things sent to the query.


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.

https://swr.vercel.app/

react-query has a nice comparison table for data fetching libraries:

https://tanstack.com/query/v4/docs/react/comparison

If routing only takes place on the client, react-router also includes data fetching features:

https://reactrouter.com/en/main/guides/data-libs

I don't know how well react-router fits with SSR.

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:

https://react.dev/reference/react-dom/client/createRoot#upda...


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?

• What cleanup does this effect need?


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.

Original: https://legacy.reactjs.org/docs/hooks-effect.html

> The Effect Hook lets you perform side effects in function components:

New:

https://react.dev/reference/react/useEffect

> 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?

[1] https://react.dev/learn/synchronizing-with-effects


> 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'd agree.

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.


What's the new way as of a few months ago? The docs way?


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.


It turns out much of s/w development is a cult (many cults) with no basis for their teachings.


> 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.

Android, too.


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.

So are the users wrong, or did you screw up?


> So are the users wrong, or did you screw up?

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.


If you're ignoring dependencies that should be on a call to `useEffect`, you're just making room for bugs.

If you're not properly tearing down what you're doing in an effect, you're just making room for bugs.

These have always been true of useEffect.


Then how do I emulate onMount now?


You have to use a useRef then inside your useEffect of [] you check if it is false and it it is you set it to true then run your code.

If anyone reads this and I am wrong please comment, but from what I can see that's the only solution.


What are the clashing philosophies?


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.


But that’s not ever what you had in React even when using JavaScript class components.


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.

I do so regularly.


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.

JavaScript is a prototype-oriented language.


> 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.


…no a function is a function and a prototype is a prototype.


So you're just gonna ignore that whole "the JS community" bit then, ok.

Is this what $200/hour consultancy looks like?


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.


OOP was invented to capture patterns already widely used in assembler and C and other old languages.


> 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.


Sure, React still supports that, for some reason. But good luck getting a job offer or even a PR approved if you're using `this.setState()` in 2023.


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.


Thanks for laying out train of thought. I have a heard time putting it into words why exactly hooks don't deliver on their promise.

> there is a class of bugs where the only solution is to change the list of dependency variables for a given hook

++ it does seem to cascade from there.


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.


How is this even comparable?

Not only React changed completely almost overnight, but the changes in the methodology were fundamental.


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.


Note that Java futures are from 2004. By the time Java 8 rolled around they definitely were "traditional".

But lambdas and everything coming in project amber, yeah, there will increasingly be many styles of Java out there.


> 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!


React Server Components (RSC) feels like the third React.

https://nextjs.org/docs/getting-started/react-essentials


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".


True, not as radical as the transition to hooks.


There are no breaking changes. Class components are still supported and used at Facebook


Class components are deprecated. They only appear in the legacy section of the reference.

https://react.dev/reference/react/legacy


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."


Oh also certain concepts and strategies are only written about in the legacy documentation. Good luck new devs!


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"


happens to lots of stuff and is not react specific


Care to source/link them? You obviously think they're important so you should do some good and share!


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.

The formal way of using React and JSX without a full SPA framework is only listed here: https://legacy.reactjs.org/docs/add-react-to-a-website.html


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.

https://react.dev/learn/start-a-new-react-project#can-i-use-...


Getting started with parcel is pretty damned straight forward.

https://parceljs.org/recipes/react/


> These APIs are exported from the react package

You can still write React the old way.


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.


That doesn't mean classes are deprecated, it means people prefer hooks, and I understand why, as someone that codes in both.

It's like saying "All Javascript things I search are only in ES2020." It doesn't mean javascript is deprecating features.


> 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.


Nobody is forcing you to use it.

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.


If you’re a principal, just ask your juniors to explain their useEffect()-based mess. When they can’t, mandate class components.


I upvoted because yes.

in practice, pick your battles.

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.


Then you get a security audit that you are not using the latest whatever and c-suites panic


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 forcing you to use it.

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.


> Nobody is forcing you to use it.

This argument goes out the door if you need to adopt a library that has already adopting them.

Even reagent, an extremely conservative React wrapper, had to provide support for functional components, hooks and effects eventually.


Yeah maybe, so? That's really not what I'm arguing about.


In the words of succession. This is not a serious product.


Akin to JS replacing callbacks with async/await:

1. You can use both styles, even interchangeably.

2. The latter is superior.

Async/await allows you to write asynchronous code in a synchronous style.

Hooks allow you to write stateful code in a stateless style.


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'!


Hooks are IMO one of the greatest innovations in UI programming.

I'll draw an analogy.

---

Why did async/await replace callbacks? They are really the same thing, aren't they? Aren't callbacks good enough?

Async/await allowed programmers to write asynchronous code as if it were synchronous.

---

Why did hooks replace classes/imperative? They are really the same thing, aren't they? Aren't classes/imperative good enough?

Hooks allowed programmers to write stateful code as if it were stateless.

    function MyComponent() {
      const [value, setValue] = useState(false);

      const buttonClass = value ? "on" : "off";

      return (
        <button
          className={buttonClass}
          onClick={() => setValue(!value)}
        >
          {String(value)}
        </button>
      );
    }
This is functional code, without scary, hard-to-reason side-effects. Except for one limited part, which operates in a stateful way.

I argue that this is simpler than the equivalent imperative-DOM modification code, and the gap between these only increases with real programs.

This isn't just a weird "web bro" thing; the hooks paradigm is useful (in theory and practice) to every UI platform.

I even wrote an implementation (closed source) for hooks in Angular. It was lovely.


This isn't "functional code" in the sense of functional programming.

It is some pseudo DSL with hidden hard to reason mutable state.


Of course it's not functional code. Just as

    let result;
    for (const item of items) {
      result = await foo(item);
      if (result) {
        break;
      }
    }
is not synchronous code. But you can write it very close to the mental model of synchronous programming.

The same is true of hooks. The code is not stateless, but you can write it very close to the mental model of stateless programming.

That is why -- despite them being optional -- hooks have become incredibly popular.


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.


Ah but if I said "async/await replaced Promises", a pedantic HN poster would correct me :/ "No it didn't replace them"


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.


I find the hooks so much easier to use than e.g. Google's ViewModel solution in Jetpack. They are just a joy to use.


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.


With all due respect, this sounds like a "old dog"/"new tricks" scenario.

"What's this .map() nonsense? The indexed for-loop always made sense to me."


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.


Redux has never seemed like a great solution for the programs I've written.

Though FWIW, MobX is far more magical than hooks.


well, those new tricks are going to bite you, later on down the road.


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.


view = func(state).

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).


> view = func(state).

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.


React Developer Tools makes it easy to inspect component state in your browser. https://react.dev/learn/react-developer-tools


> 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.


I think that view = func(state) is an unnecessary complicated way to describe frontend development.


After years of react dev that is probably one of the wildest takes I’ve ever read. Kudos!


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."

Hopefully you can appreciate the difference.


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.

Hopefully you'll click on it someday


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.

https://nakedjsx.org/documentation/#getting-started

EDIT: clarity


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.


React popularized and brought one way data flow, and Redux introduced centralized state which was a massive improvement over AngularJS.


> 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.


It's good that I wrote:

> 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.


Uh, the style of it is extremely functional-like, even if it’s not actually functional.


What about it is "functional-like"? Does functional simply mean not using classes?


Why is it fundamentally inconsistent?



Yup! I actually discovered react via Om, which lead my down a delightful mind bending journey into ClojureScript and lisps. Awesome


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?


Finally all those job postings asking for 10 years of React experience can be filled!


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!

Thank you React dev team.


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.


Embrace it for awhile and it really is special.

You've a function that returns JSX which is your HTML where you can use Javascript to reference functions/variables (e.g. the state variables)

One of the key parts is that you can break it all down into different files/functions that return jsx so you can isolate complicated parts


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?


Similar feelings here. To me, React was one of the first approaches to web frontend development that really promoted good engineering practices.


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.


Which one? This sounds like it could be useful for me


After some digging I believe it's this one: https://github.com/lookfirst/mui-rff


Cheers


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.


> a literal 5-20x productivity boost

Not really. See a better way here: https://github.com/wisercoder/eureka


Sorry, I don't understand. Why is this a relevant link?

"Lucene based search" vs React ? Seems like comparing trees to tractors.


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.


Got it thanks for the context.

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.

FWIW, the reason this works for eureka is highlighted best on this page: https://github.com/wisercoder/eureka/graphs/contributors there is only a single author!


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.


I'll try one last time:

> Sorry none of this makes any sense to me.

If you're not familiar with the MVC variants (MVVM, MVP, MVI, MOVE)[0][1] we should start there.

Next you should read through some common mistakes of Backbone.js like applications https://www.toptal.com/backbone-js/top-8-common-backbone-js-... and some criticisms of MVC on HackerNews in 2012[0].

Finally if you haven't before these talks, they are the ones that sold me on React:

- https://www.youtube.com/watch?v=-DX3vJiqxm4

- https://www.youtube.com/watch?v=DgVS-zXgMTk

- https://www.youtube.com/watch?v=nYkdrAPrdcw&t=203s

[0] https://medium.com/@pinarkocak/mvc-mvp-and-mvvm-design-patte...

[1] https://news.ycombinator.com/item?id=4189811


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?


Backbone.js used 2-way data binding. Some people mistakenly think MVC implies 2-way data binding. It does not.

The point here is that you can write maintainable, clean, efficient JavaScript web apps without the load of complexity added by React.


> Backbone.js used 2-way data binding.

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.


There's still truth to that. React has changed a lot in those 10 years. So much so that old code is unrecognizable and would be an anti-pattern today.

And that's only React, the ecosystem around it also has changed significantly.


10 years old and the only reliable official docs on how to use react came out just 2 months ago: https://react.dev/blog/2023/03/16/introducing-react-dev


They had a tutorial and reference 10 years ago:

https://web.archive.org/web/20130607112825/http://facebook.g...


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.


> As you know, Java and PHP are languages. React is just a framework,

Ok then, what about the Spring .xml to .java migration? What about the Struts -> Struts2 -> SpringMVC -> SpringWebapp migrations.

It seems an unfair criticism of React.


> 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.


> Back in 2015, $JOB was evaluating upgrading Java 6 to Java 7 or 8. What is now? 20?

And how much have you had to rewrite or replace going from 8 to 20? Very little, right?


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.


Are you still using Redux and classes? How's that working out for you?


Django is just one example. There wasn't major change for how the whole application is being written


I was blown away when I learned the concept of the virtual DOM and how diffing it could be made fast.

But as practical tool, React has been a regression for the web IMO.


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.


How has it been a regression for the web?


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.


> I don’t think direct DOM manipulation was ever a problem, if done thoughtfully.

Then you've never worked on a medium/large UI application (1k+ LOC), and most certainly couldn't have lived through the era of DOM manipulation!

jQuery when it first arrived was a god-send! but even the most thoughtful couldn't structure it right.

Backbone when it first arrived was a god-send! but even the most thoughtful couldn't structure it right.

React when it first arrived was a god-send! but even the most thoughtful still can't always structure it right.

With, the inclusion of so many other failed and semi-successful attempts throughout history I have no idea how you can possible claim:

> I don’t think direct DOM manipulation was ever a problem, if done thoughtfully.

without just being naive...


24 years of web development here. Large code bases and I still love jQuery. Whenever I can avoid React, I do.

htmx is the first JS thing to tickle my curiosity in a long time. Vue seemed fun at first, but it got more complex than needed, IMO.


> 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.

Regarding templating engines, I use PHP :)


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?


Compared to what I would imagine such complicated scheme would be. Turns out, computers are fast and diffing algorithms are fun to tinker with.

Also, you don't need Virtual DOM to have declarative UI, just ask Svelte.


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.


To celebrate React 10th anniversary, Next.js interviewed Andrew and Sebastian from React core team: https://www.youtube.com/watch?v=g5BGoLyGjY0


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?

Edit: Is this the place to start? - https://react.dev/

From what I see from the tutorials...Why the closeness to NodeJS?


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.

1. https://parceljs.org/recipes/react/


Hi, I'm a Redux maintainer and creator of Redux Toolkit.

Can you clarify what your concerns are with RTK?

We specifically created it to simplify standard Redux usage patterns and eliminate common mistakes and bugs (like accidental mutations):

- https://redux.js.org/introduction/why-rtk-is-redux-today

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:

    import { createSlice } from '@reduxjs/toolkit'

    const todosSlice = createSlice({
      name: 'todos',
      initialState: [],
      reducers: {
        todoAdded(state, action) {
          const { id, text } = action.payload
          state.push({ id, text, completed: false })
        },
        todoToggled(state, action) {
          const matchingTodo = state.todos.find(t => t.id === action.payload)
          if (matchingTodo) {
            matchingTodo.completed = !matchingTodo.completed
          }
        }
      }
    })

    export const { todoAdded, todoToggled } = todosSlice.actions
    export default todosSlice.reducer
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:

- https://redux.js.org/tutorials/fundamentals/part-1-overview

Ultimately it's your codebase, but we really do _strongly_ want everyone working with Redux to write that code with RTK.


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.


So now all those ridiculous job postings requiring 10 years experience with React finally make sense?


It should be 15 years of experience now.


Congrats Dan and everyone on the React team. Great framework and has been an extremely productive decade for me personally.


10 years and state management is still a mess.


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.


Can we agree it's not a "framework du jour" anymore? 10 years is a pretty long day


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.


What will succeed React?


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.


Absolutely agree! Vue + Pinia = This is the way ©


Succeed implies that it reigns supreme. But Vue and Angular has been significant for a long time now.

https://survey.stackoverflow.co/2022/#section-most-popular-t...

My bet for next-gen frontend tech is on svelte and SolidJS. They are faster, lighter and their tooling scene isn't as fragmented.


Looks like jQuery might get a comeback before vue and angular do anything based on that graph


Sure, if you consider 18% and 20% as doing nothing.


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:

async function MyComponent() {

  const data = await db.get('...')

  return ...
}

https://nextjs.org/docs/getting-started/react-essentials


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!


In my opinion? GTK on Wayland under WebGPU. You laugh now...


2030 will be the year of the linux desktop


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.

Other than that, prob. lit-dev (with time).


> Other than that, prob. lit-dev (with time).

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.


Sanity hopefully


big milestone for the team, congrats to all of the contributors!


React - you have a special place in my heart


The only good thing about it, it's JSX! \m/ The rest is abomination ¬_¬




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: