Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
React Labs: What We've Been Working On – February 2024 (react.dev)
113 points by thunderbong on Feb 27, 2024 | hide | past | favorite | 123 comments



For some reason, I see people in this thread whom I believe don't really understand why hooks were invented. Put simply, just like closures hold state in a function, hooks compartmentalize the component's lifecycle, they are basically `function(state, lifecycle)`. I linked to a Flutter thread elsewhere (on the topic of adding hook-like constructs to Flutter as well) that I've seen as one of the best examples of why class components simply cannot replicate the effects of hooks, due to the inherent limitations of classes [0].

The author uses an example of needing to initialize and dispose of a variable, and you must do this manually each time, for each variable. With a hook, you can abstract this behavior and say, given this lifecycle, I need this variable to be automatically initialized and disposed at the correct time. I write it once, and don't have to think about doing it manually anymore. Hooks are an abstraction over lifecycles, just as functions and loops are an abstraction over repeated procedures.

[0] https://github.com/flutter/flutter/issues/51752


I am certain your comment was well intentioned, but it is quite striking how frequently the you are arguing against it, so clearly you must be an idiot defense pops up any time someone criticizes React[0].

[0] https://news.ycombinator.com/item?id=35278169


I'm not saying they're an idiot, but it takes time to learn tools. Frontend devs and React devs in particular are usually more novice than other types of coders (in my experience), likely due to so many courses pushing out MERN devs over the last 10 years or so, so it is very likely that most just went with the flow and never actually sat down to read the docs and understand their tools.


Isn't this an implicit argument in favor of simpler tools with less thorny undersides than React Hooks?


Sure, but every technology has its own problems. It just depends which tradeoffs you want to make.


> One way to think about this is that React currently re-renders when object identity changes. With Forget, React re-renders when the semantic value changes — but without incurring the runtime cost of deep comparisons.

There's got to be another word for 'magic' to describe this kind of behavior because this is on a whole other level. People complain about observers, or transpiling being too magical, but at least those are straightforward in principle. I can see Rich's video on how svelte works and more or less get it, it's just that it happens implicitly. Semantic value here would depend entirely on the data type; I have no effective way of being sure of what is being implicitly generated.


> There's got to be another word for 'magic' to describe this kind of behavior because this is on a whole other level

As far as I understand that quote, it's just about "reference equality" vs "value equality", something most programmers deal with often but maybe frontend programmers aren't used to it? Not sure why the quote doesn't include that naming for it, maybe it would help people connect it to concepts they already understand.

FWIW, I also think React has gotten to complicated and bloated, but I've been thinking that since hooks were introduced if not before, and mainly use React indirectly via Reagent, not directly.


I think they're doing a little bit more. I should've linked the article I quoted since it's not in the submission post but a link the submission post, from march of last year.[0]

They go on to explain :

> Under the hood we use a custom code representation and transformation pipeline in order to do low-level semantic analysis. However, the primary public interface to the compiler will be via Babel and other build system plugins. For ease of testing we currently have a Babel plugin which is a very thin wrapper that calls the compiler to generate a new version of each function and swap it in.

> As we refactored the compiler over the last few months, we wanted to focus on refining the core compilation model to ensure we could handle complexities such as conditionals, loops, reassignment, and mutation. However, JavaScript has a lot of ways to express each of those features: if/else, ternaries, for, for-in, for-of, etc.

[0]https://react.dev/blog/2023/03/22/react-labs-what-we-have-be...


Oh wow, yeah, that definitely sounds like more magic that I thought at first. Thanks for expanding the context a bit :)


The problem is a library changing language semantics mostly as a consequence of their own earlier design decisions.

So I can totally explain someone how there is no pass-by-reference in Go, and I can also explain why equal sets of different identity are not really equal in JS (following the records proposal, with my fingers crossed, and happy with it because it's a language change), but when libraries introduce different semantics via their own compilers, that's a line I don't like getting crossed.

That's actually why I never really got into Svelte.


Evan You (Vue author) had a great quote about this:

    A mutable model that you can reliably understand is better than an immutable one that leaks.
    
    The pain and suffer of hooks all roots from the mismatch between a dogmatic belief in the superiority of immutability and the harsh reality of the host language that is JavaScript.
React's render cycle is fundamentally mis-aligned with JavaScript since the re-render requires that you correctly manage state and references in the path of the render cycle by moving it out of the way with a hook.

It all feels quite unnatural as someone who has been writing JavaScript since the last 90's.

https://twitter.com/youyuxi/status/1629636673519894528

https://twitter.com/youyuxi/status/1629636967473496064


I agree with the sentiment that JS is the wrong language for React, but it’s not such a big deal in practice.

The key is to write your own hooks specialized for the project, then the complexity is isolated into one place where you are expecting it, instead of dispersed across your project. If you are trying to write everything using the built-in hooks then you’re going to have a bad time.


    > you’re going to have a bad time
Have a good time and use any of the other options available. Vue, Solid, Preact, Svelte, Lit, Vanilla.


It makes sense when you realize that React concepts were originally conceived in OCaml by Jordan Walke, who also made ReasonML as a JS(X)-like syntax over OCaml. OCaml is almost all functional, with immutable variables, so this was brought over to React.


I don't think React is approachable. It is just the most popular framework and has the biggest ecosystem, that is why it is used. Otherwise it is just not good in my view compares to others.

Also I don't think useMemo or useCallback were a reasonable compromise ever.


My initial reaction to a Tweet from Andrew Clark on the upcoming compiler motivated me to write[0]:

    React is the new IBM: you should learn it, you should understand its faults, you should probably still deploy it. You’ll never get fired for picking it, but it’s going to be expensive, bloated, difficult to get right, and it’s going to be joyless implementing it every step of the way. React is “the status quo mindset — the biggest enemy of pure innovation”.
I think the project has completely gone off of the rails and is now going through these cycles of self-inflicted complexity only to be solved several releases later with additional complexity. All the while, not really addressing the core issues that affect DX and ergonomics.

React is the new IBM.

[0] https://chrlschn.dev/blog/2023/02/react-is-the-new-ibm/


It became the most popular in the landscape where all kinds of other frameworks existed. Because nothing beats immediate-mode-style API in terms of code clarity.


> Because nothing beats immediate-mode-style API in terms of code clarity.

This is not React these days at all. Maybe when it was just an actually useful library. Not a hope now.

> It became the most popular in the landscape where all kinds of other frameworks existed

It became popular because it was simple, when it was simple. Then they did what all JS developers do. Find a problem for a solution.


Did you write React with class-based components? Do you think CWM/CWU/CWRP is better than useEffect, or constructor/setState is better than useState?


Yes, because those methods were actually obvious and said what they did.

Hooks are very non obvious / full of gotchas, and made react code no longer "just javascript".


at the time Vue is had it right but the people wanted TS and that wasn't a good UX for too long in Vue.

now it seems the magic Vue had has gotten better, and was copied over but worse to react.

if react can fix it by compiling it away, cool. but fixing computer bugs is even less approachable than webpack.


React like angular seems to me very much a solution from a bygone time. The time when internet was slow and expensive.

I find very little reason for anyone, except services in the insta scale, to actually use this abomination, since CSS and html deliver the same user experience with plain SSR.


The internet is still slow and expensive for huge swathes of the world.

React is still not a better option for them.

The truth is that React was very good and probably would have remained pretty good to great even today if the original form had been iterated upon.

What we’re seeing today is nothing like the original react and should have been a completely different library in the first place.

I suspect if this completely library had been created without the advantage of piggy backing off the original highly successful React library’s fame, it would have made little to no headway on its own strength.

Heck, I’d be open to an argument that what we’re seeing today, a DSL that’s focused on making NextJS work, could even be considered a 3rd or 4th different library under the React moniker, after original React, hooks based React (even here the goal and meaning of hooks changed midway) and then the current NextJS DSL.


I get that some people only work on web pages, but can we at least have some acknowledgement that web apps exist?

Some people (me) use React to build interactive web apps. That’s what it was designed for, and it works rather well. SSR is completely useless for me.


It’s getting harder to keep track of all the shiny new features. UI devs already deal with TS->JS compiler, tailwind compiler just to name two. Can’t imagine adding another compiler to the mix. Our already complex and fragile build pipelines just keep getting worse.

I understand the problems in scaling UI development. Just don’t think the solution is to build another layer of complexity atop the shaking foundation.


> Just don’t think the solution is to build another layer of complexity atop the shaking foundation

Why would we try to solve UI development issues any different than other parts of the stack? Building layers on top of shaky foundations is a true and tested approach in computer science and seemingly the only way to move forward somewhat.


All these features sound interesting in isolation, but I can't help thinking that react is stuck on the same treadmill its been on for years.

They keep solving important problems like memorization bugs, but these problems are all self inflicted. The API keeps getting more complex, and with a goal of backwards compatibility everything is additive.

Actions as a generic concept look interesting, but the idea of having every library expose both onSubmit and submitAction is just going to make things more confusing. I guess you use events for old code, and actions when you want the option to send the event to the server depending on the "use server" directive or pragma? And when the next thing comes along, I guess every library exposes 3 different ways to handle a form submit event?


Lots of valid points about the increase in complexity for React over the years, and that one should pick another more modern tech stack (Svelte, Solid, html, whatever), and I used to be thinking like that

But since maybe 1-2 years, I am back and betting on React for most of my serious projects (for the ecosystem, the ease of hiring, etc), but the most important point is the following:

React backwards compatibility is really good, and will stay so for a good reason: a LOT of Meta’s UI code is using old features (classes syntax etc), and Meta cannot afford to break those. If there are breaking changes, they must be “codemodable” (so, usable by everyone).

Meaning in terms of stability, I know my codebase today will still work fine in years ( or upgrade-able with minimal efforts). Of course there will be new shiny features, but I or my team will not have to rewrite old code all the time following tedious migration guides.

disclaimer: I am kind of biased as I work at Meta, but far from React.


So, your team upgraded to React 18 without having to rewrite anything?


The person you're replying to did not say that, you're arguing against a straw man. Looking at the manual, upgrading to 18 seems straightforward, matching the "minimal efforts" they mentioned: https://react.dev/blog/2022/03/08/react-18-upgrade-guide


Arguing isn't the correct word for that. I did express incredulity when asking for clarification.

The person I was replying to did minimize the effort involved in upgrades by enclosing it in parentheses.

The incredulity is based on experience. Sure you can follow the upgrade guide, and if you work at Meta there are many people that know about weird edge cases. If you don't work at Meta, then you may be spending time chasing down bugs in production on your own. That gets expensive.


I like about Vue that everything feels straightforward and if fits in my head. In other words I think it's powerful and at the same time simple. It had only once a big change, and even then it was very easy to understand. If you knew the options api, the composition api was very easy to understand.

Maybe Svelte is also like Vue, I haven't tried it. I've heard many react horror stories but I've never used it, so I don't know how true they are.


MobX and chill.

No compiler necessary.

If React created better extension points for pluggable reactivity we wouldn't even need observer() wrappers. This is all getting kinda bonkers.


MobX re-introduces all push-reactivity problems that React removes.


Can you elaborate on this? React's in-built reactivity system via props and context are certainly push. I'm not even aware of a pull-based reactivity system.


React developers wrote about this here: https://legacy.reactjs.org/docs/design-principles.html#sched...

Let me try to explain this differently:

A typical reactive framework architecture (RX, Knockout, etc) looks like this

Events -> Observables -> Computed values -> Subscriptions -> DOM updates

It aims to provide a targeted DOM update in response to event as soon as possible, but it has several major disadvantages:

1. Batching and prioritizing capabilities either don't exist, or are limited and generic, in particular by default they are not tied to UI structure, because the framework itself doesn't want to be aware of UI structure, it just wants the framework user to provide event sources and write update targets manually.

2. Computed values are computed if corresponding subscriptions are active. In contrast, React hides state propagation logic inside the component tree, so the computation happens only when components are actually rendered.

Issue 1 is not relevant for MobX-React case, because React is doing UI update batching and prioritisation. But issue 2 is very real, especially when using React Router. I had multiple cases where Computed values were computed at unexpected point in time and used observable values that were not initialised, while corresponding React components were not even visible on the screen.


It can do it but not necessarily. I think in strict mode only actions can modify state and if you use reactivity only for rendering then it great


+1 for mobX. Dead straightforward, does one thing and does it well. Only worry is that it increasingly feels like an outsider in React. I'm working on an app that uses React, web components and mobX, and upgrading to React 18's concurrent rendering breaks stuff, and I'm not sure which of my relatively niche technologies (mobX or WC or maybe the interaction of the 2?) causes it.

Preact has been looking increasingly attractive as a library that does its own thing and nothing more. Anyone knows if preact signals are basically a drop in replacement for mobX?


Yeah, it's bizarre how it's essentially been doing what all these newish(past 4 years or so) state management libraries and frameworks are rediscovering the entire time and yet.. It gets snubbed. Not even mentioned as a state management library by Tanstack Query. Always left out of the conversation. And yet, AFAICT, it's actually pretty quietly, and heavily used in the "app" space by a bunch of very large companies.


MobX is how you get spaghetti code and state changes everywhere. That is why we (our company) moved away from the observer pattern that MobX and RxJS use.


What did you move to?

I've seen plenty of spaghetti code with just about every other React state management (reactivity) approach. The benefit of MobX to me is I can write a more traditional "domain" layer and wire the view in on top of it keeping a good separation between business/domain logic and UI concerns.


Can anyone clarify how the compiler would fit into the workflow? Are we talking some kind of CLI that takes a JSX/TSX entry point as input and outputs a compiled JS bundle, like a replacement for Webpack/Rollup etc. but more specialised to optimise React code? Or something more fine-grained that operates on a single component/module at a time? Or something else?


The idea is that it should eliminate the need for things like useMemo, useCallback, etc. it seems there’s better support for promises, as well.


Thanks but this isn’t what I asked about.


Learning about the auto-memoization feature when it was called React Forget made it seem like a pretty natural extension of the functional component paradigm - separating out and memo’ing parts within components based on info that’s trivially available at compile time (maybe not trivial, I’m not sure how much work is being done by the compiler here). Is this something that could be implemented as a language-level feature for some “dedicated” language for writing functional reactive UIs? Languages like ReasonML are meant to map more nicely to React’s model because of their expressiveness, but I wonder if it could be taken further.


At this point people should already be looking to move away from react to something better like svelte, Vue, htmx.

Why anyone would start a project with react in 2024 be beyond me.


For crossplatform mobile development, the only viable solutions in 2024 are React and Flutter, and the former has a wide ecosystem already while the latter uses a programming language, framework, and ecosystem only used in that particular use case.


The goal behind "hooks" was to make React simpler for beginners. I build client-side apps since 2007, and React is getting too magical and complex for even for me. The NextJS influence is really making things worse, "use server" "use client" tags do not scale at all. The project clearly lacks mission, goal, leadership and direction. I'll use Preact in the next projects.


> The goal behind "hooks" was to make React simpler for beginners

No, it had nothing to do with making it "simpler for beginners." It was to functionalize state changes in a way that was impossible with classes and other OOP constructs like mixins. There is actually a great issue thread on the Flutter GitHub that explains exactly why other solutions do not work correctly when compared to hooks [0]. What people don't get about hooks is that they are an abstraction over state and app lifecycle changes. It is better to think of them as akin to closures but over lifecycles, not just holding state as closures do.

[0] https://github.com/flutter/flutter/issues/51752


> There is actually a great issue thread on the Flutter GitHub that explains exactly why other solutions do not work correctly when compared to hooks [0]

Interesting. I assume you are referring to this comment in particular -> https://github.com/flutter/flutter/issues/51752#issuecomment... ?


The whole thread is worth a read, the first post in particular lays out why traditional class-based solutions don't work, while that comment by Dan Abramov is good in its own way, viewing hooks through the lens of algebraic effect handlers.


> No, it had nothing to do with making it "simpler for beginners."

Open up the announcement of hooks by Dan Abramov and listen him.


I've seen this criticism several times on HN, but have never been able to relate to it.

I've been using hooks since they were introduced, in several teams (at several different companies), and I've never experienced them being complicated to understand, either for myself, or for team mates - even juniors who are new to React. In my experience, it takes very little time (<1 hour) to understand the basics of React, and once you have that mental model in place, hooks fit in immediately.

I wonder if it's the case that many people on HN are just used to some completely different libraries and thus are coming in to React with a completely different mental model? And that's the cause of this sentiment being so common here.


> I wonder if it's the case that many people on HN are just used to some completely different libraries and thus are coming in to React with a completely different mental model? And that's the cause of this sentiment being so common here.

Nope. For me React was the first frontend framework I learned. The mental model of Class components was really easy to understand. I have since "learned" hooks, but they are a constant source of mental exertion for me, and it's very easy to make mistakes. Kind of like all the other "improvements" that they brought to React since Class components.


You might be interested in learning the reason hooks were invented [0]. I also use hooks in Flutter via a separate package and its creator made a great GitHub issue talking about exactly why class components cannot replicate the hook model [1], simply due to the limitations of how classes work. The code is in Dart but it's simple enough to grasp if you know JS and class concepts in general like overrides and mixins.

[0] https://medium.com/@dan_abramov/making-sense-of-react-hooks-...

[1] https://github.com/flutter/flutter/issues/51752


I do not get that class components are in any way simpler. Before, you had to think about explicit configuration states during the components entire lifecycle. Now, you just... don't?


Previously everything was explicitly in your code. Now everything is done with "magic" outside your code. You're saying that this is better because now I "don't have to think about it". But I do! When something doesn't work, you have to figure it out. It's easier to debug code that you can see and reason with, and more difficult to debug a black box that behaves in mysterious and unexplainable ways.

What you're probably thinking is "it's faster to write a TODO example app with hooks". That's not really relevant for actual software development.

It seems that framework creators are constantly making tradeoffs where they are making the easy things easier at the expense of making the hard things harder. That's the wrong tradeoff to make.


That's interesting. My feeling is that things became MORE explicit with hooks, not less, so I'm quite confused still.

> What you're probably thinking is "it's faster to write a TODO example app with hooks". That's not really relevant for actual software development.

For me, that's not the case at all. I think with hooks, it's easier to reason about what values are actually used during what renders.


> For me, that's not the case at all. I think with hooks, it's easier to reason about what values are actually used during what renders.

Hmmh. Can you provide me an example of what would've been "unclear" if the value was just state in a Class component?


I can objectively prove that React devs themselves have at the very least changed how they understand hooks but more likely have been making it up as they’ve gone along. The best example is one of the more problematic hooks, useEffect.

Here’s how useEffect is described in the old documentation:

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

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

Here’s how the new docs explain useEffect:

> useEffect is a React Hook that lets you synchronize a component with an external system.

These are dramatically different claims about what useEffect is supposed to be for. Dig a little deeper and Reaft developers will now explicitly tell you to not use useEffects for side effects, which again is the opposite of what they explained it to be.

The same change in how they’re actually supposed to be used has been true across all the books to a lesser or greater degree.

Maybe React has finally stabilized and it’s easier for new devs because they’re learning the more stabilized version. However, I suspect it’s easy because they just happen to be within the same cycle of understanding in React. Much like how React was easy for devs coming to it nearly a decade ago, until the devs changed everything about it. New devs may just not be deep enough into the new cycle to experience the pain of all your understanding being wrong.

Now, to be completely clear, I have no problem with the changes. I think change is good and I have successfully worked with languages where the change has been even more dramatic than React.

The difference with React, I’ve increasingly come to realize, is that the developers will make radical changes in how they understand it to work, while still gaslighting you that nothing really has changed.

Hence the massive effort they made to convince everyone that hooks were just a different approach as classes and they both would be first class citizens forever, when they first introduced hooks, only to subtly and quietly change the narrative to hooks being the future of Reaft and recommending hooks.

They make these shifts all over the place without ever announcing it and convincing you to believe that what they’re saying today has always been the case.

More honesty towards how they’re changing React and what those changes mean would have gone a long way to reduce the absolute confusion floating around the react world.


I think it’s more that the React team’s way of articulating their idea of what a “side effect” is changed than that their idea of what useEffect is for changed. The examples of “side effects” in the old docs are all cases of “external synchronization”. People found the old terminology misleading because they came with their own preconceptions of what a side effect is, so they changed their pedagogical approach. The technical details haven’t really changed, just the presentation.


I've worked on some pretty complex client side code and frankly react hooks are meh at best.

There is a very strong implication in the docs and even the overall solution of hooks to ignore the details and just "go with it".

Just do it™ our way™ because reasons™

Generally not healthy for building the level of understanding it takes to debug complex react code.

Also I deeply on a spiritual level detest the way that it very strongly incentivizes pushing business logic to the view layer.


I'm building frontend apps since 2012. I did not like hooks but ok fine. But NextJS seamed to became the default way of building React apps. I could never grasp how people in twitter and everywhere seemed to be fine with all this complexity it brought. All of this for reducing some milliseconds in load times? How can this be the default? With create-react-app you could just compile your app and host it at S3 with CDN for pennies. With NextJS you can do static site but you have to be aware of several gotchas. It seems like made up problem and solution to make return for the VC money, what am I missing?


I feel embarrassed when some of the great back end / system programmers I work with have to go in the front end code base and write React. They can submit patches to linux source like it's nothing but understanding React is just too hard for them.


I'm not on that level, but diving into React when you're not used to it is quite an experience. I've been asked to do it a few times as a most-backend/infra person. Good luck when the codebase is a mess though, cuz it seems like React spaghetti is a special breed of spaghetti.


There’s an interesting assumption here that frontend engineering should always be very simple, such that engineers in other disciplines should be able to hop over and dabble with frontend engineering on the side with no difficulty. Or perhaps the assumption is that React specifically should only focus on the fluffy, junior-friendly end of frontend and leave the more advanced frontend stuff to other toolkits?


I think React (hooks) invents a convoluted solution to a problem that can be solved in a more direct way, and there's a lot of big caveats hidden behind the interface that can cause big performance problem and bug. Their invention also requires a specific way of thinking that contradicts a lot of programming intuitions. Complexity is definitely fine if it comes from the problem itself (rendering), but for React most of the complexity is introduced by itself.


I'm confused why you feel embarrassed? Do you think they feel embarrassed that you can write React yet don't know how to write patches for the Linux kernel?

It's a different domain with a different skillset.


I meant I was embarrassed that these experienced engineers have to put up with some of the bad parts (I think) of web dev, that React (hooks) has a lot of unnecessary complexity and requires some unique mindset you have to train specifically for, unlike other frameworks have more direct and more intuitive solutions to the problem and I believe will be trivial for these engineers to get a grasp on.


React is fine, but what is going on with RTK? So. Much. Boilerplate.


Hi, I'm a Redux maintainer. I'm kind of confused by your comment in a couple ways.

I'm not sure why you're jumping to discussing Redux here - we're a completely separate project from React, and nothing about the parent comment mentioned Redux.

That said, we specifically created and designed RTK to _eliminate_ boilerplate, so I'm not sure what "boilerplate" you're referring to here. Could you give some specific examples? What concerns do you have?


I’m neither a React nor Redux developer, but I work on React codebases. The code I see for simple changes is super verbose compared to what it would look like with simple hooks. I don’t know if it’s just my coworkers that suck at it.


Redux will never be the _absolute_ shortest way to write updates - it intentionally adds a level of indirection (the concept of "dispatching actions").

That said, we specifically created Redux Toolkit to drastically simplify standard Redux usage patterns. Sadly, despite it being the default way to write Redux apps for several years now, there's still a lot of legacy Redux code that isn't following our recommended patterns.

See our "Migrating to Modern Redux" guide for details:

- https://redux.js.org/usage/migrating-to-modern-redux

as well as the "Style Guide" best practices page:

- https://redux.js.org/style-guide/


> The goal behind "hooks" was to make React simpler for beginners.

What makes you think this was the goal? React team has been trying to get rid of 'this' for a long time; I believe I saw someone say that it had some undesirable consequences for the fiber architecture and for the "concurrent mode" that eventually was transformed into a set of concurrent features. Alternatively, it is possible that they wanted a better reactivity model than the one based on component's lifecycle. Why does this necessarily have to be simpler for beginners?


Examples from the conversations of that time:

> ...we want closures to capture the values we rendered with, and to keep "seeing" those values forever. That's really important for concurrent mode where a notion of current value doesn't really exist. Hooks design models a component as being in many non-clashing states at the same time, instead of switching the "current" state (which is what classes model well). People don't really need to think about these details, but they're motivating the design a lot. [0]

> In Concurrent Mode, render may run more then one time, and since this in a class is mutable, renders that should be the same may not be. [1]

[0] - https://github.com/reactjs/rfcs/pull/68#issuecomment-4778866...

[1] - https://tkplaceholder.io/why-function-components-fit-react-b...


Can't help but agree. It's very hard, even for experienced developers, to understand what is going on with hooks.

Even knowing why they are needed requires a deep understanding of what is happening.

Definitely feels like complex implementation details leaking upwards and influencing the public API.


Personally I appreciate the ideas behind hooks, but the implementation feels like I’m trying to write in a different language behind JavaScript that has its own rules about scope, flow control, variable dependencies, and many other things that run counter to what appears to be happening on the JavaScript surface.

I’ve worked on many projects that implemented object-oriented programming in C, and the impedance mismatch there was much more tolerable. That should be a warning signal that something is amiss with hooks in JS.

They made an embedded language extension for JSX. Why not a similar separate language for hooks, to clearly delineate when you’re working with the React state machine rather than ordinary JS state?


I was able to grasp hooks after an initial distaste. But once I started hearing about hydration, I just felt this…weariness. It’s why I’ve never been interested in NextJS and definitely not interested in RSC.

I’m open to having my mind changed, but I really don’t like having abstractions cross the network boundary.


> Definitely feels like complex implementation details leaking upwards and influencing the public API.

This describes it very well. I recently started writing React code after using Vue 3's composition API for a long time, and it's hard to explain just how much more low-level and manual the primitives feel.


When hooks were first announced they had a bit of a "you probably shouldn't use this unless you're framework author" air to them.

I'm not sure if it was the react team adjusting the message and pushing for hooks in user code, or users throwing hooks at every problem when that wasn't recommended, but it definitely got odd track.

I still like hooks for internal code in libraries and frameworks, but they ruin client code IMO. Unfortunately hooks are here to stay and there's really no way to avoid them in most apps today.


I have a similar experience to yours. I'm using preact for most things now, sveltekit for anything full-stack or when I need static generation (great fro small/mid-sized projects, haven't build anything "enterprise" with it).

I wish Remix was preact. It looks like it has parts of preact and svelte I really enjoy.

I've been using Next.js since 2016/17 at small and large SaaS scale) -- I feel like they're building it like a VS funded SaaS now. The added complexity doesn't really pay off.


I haven’t done serious front end work since years, so I’m not up to date with recent solutions. The current project I contribute to has a Next.js app for its front end. The web app has maybe 4-5 pages, only one is pretty heavy (a sort of IDE like web UI). I’ve never experienced such a sluggish tool. next dev consumes a massive amount of memory and is really slow, next build takes minutes to compile pages… I’m pretty happy I’m not touching the front end regularly, I’ve mostly noticed the slow build times when creating a docker image (it takes ~10min to build in a CI context, most of that time is waiting for pnpm install and next build to finish) and setting up some continuous deployment pipelines.

I really feel bad for anyone who decided to go with that stack.


I have made hard decisions to fully return to vuejs for a few months, much simpler.React has lost itself totally thanks to vercel/next.js who hijacked oss projects for its short gain with VC's money.


If you look at their incentives differently, i would argue they doing well with their goals. Every "use server" is another vercel customer. Every preact user finds it harder to claim they are using react when apis showing up in react canary and being documented for nextjs don't exist for them.


React isn't a Vercel product though, and server components are a react feature rather than a NextJS feature.

With regards to incentives, these newer react features only meet their goals if the goal is to use react the open source project as a funnel for Vercel, the for profit hosting company.


Most of the core React devs are employees at Vercel. As much as you may not like it, core parts of React are driven by Vercel 's business model.


Most? Looks like 3 out of 20 people

https://react.dev/community/team


Is React no longer a Facebook/Meta project?


Same realization. I started playing around with Rails/Hotwire and found that to be much more productive and far simpler. Haven’t used it for anything “real” yet, but I am enjoying it so far.


I couldn't agree with you more, but sadly the amount of inertia around React makes it very difficult to ignore or supplant. Especially if you're in the business of providing any kind of developer tooling.

The project I'm most excited about in recent years is htmx. Sadly I've yet to have the opportunity to work on any real projects with it. Some day, fingers crossed!


I agree but a major selling point of React is its ecosystem, and libraries are not compatible with Preact by default


Which libraries have you had trouble using? The official preact/compat library works great for me https://preactjs.com/guide/v10/switching-to-preact/


A lot of throwaway accounts on here recommending people switch to vue in 2024.

At least for now, I don't see any urgency to switch from React. There's more React developers than Vue, Angular, Svelte, htmx, and Solid combined. React is not quite as ergonomic as Vue or Svelte, but all are swiftly approaching feature parity.

Vue and Sevlte don't seem to represent a big enough boost in productivity to justify rewriting an entire generation of codebases.


To latch onto this comment; never switch an application's primary framework for the sake of switching. Consider other things, like time spent maintaining, hiring, training and onboarding required, support, etc.

Anecdote, we switched to React Native from a thing called Nativescript, primarily motivated by the dwindling development and support, and the huge overhead that Nativescript brought.

But I have to hold my hand up and say I didn't like Angular and the redux-style beating around the bush either.


So thats why CRA has been left to die?



What's the connection?

Also, take a look at this response from 2021:

"Like I said earlier, it was always the intention that we're not going to be able to work on it full-time... [I]t was intentionally designed for this kind of sporadic development. We would get critical fixes out as soon as posible, but overall, starting with 2.0, it's mostly in maintenance mode and does not strive to be the best tool for production React apps. It is a tool to get started and get something running fast. Perhaps, it's not even best at that anymore."

https://github.com/facebook/create-react-app/discussions/117...


A new solution could replace some of the tools we use today, making it obsolete and not worth maintaining in the future.

Make sense, but the lack of an "oficial" solution doesn't help https://react.dev/learn/start-a-new-react-project


I have been tempted to go back to turn of the century tech: html tables for layout with inline css for styling and smarty template for separation of concerns all driven by php.


> html tables for layout with inline css for styling

Html and css have only been getting better over the past two decades; they are not the problem; no need to resort to inline styles and tables. As for going back to server-side templating with php, this is a very good option.


CRA was never a fully official project, though there was a lot of confusion around that. It was in a weird semi-official state, it certainly had the endorsement of the React team initially but it didn't have actual resources from Meta behind it.

CRA was useful when it first appeared because the whole space was a big mess. But it very quickly outlived its usefulness, and its approach was really problematic in my opinion. The config was too complex to eject and modify compared to what you could do yourself with Webpack directly.


> CRA was useful when it first appeared because the whole space was a big mess. But it very quickly outlived its usefulness, and its approach was really problematic in my opinion. The config was too complex to eject and modify compared to what you could do yourself with Webpack directly.

Yes agree, but writing and marinating config for multiple projects just don`t scale. Not to mention we need something dirty and fast.


my 2c: still does the job without ejecting on my small project. Just reading your comment made me happy I don’t spend time thinking about webpack configuration


Until you run into any problem that you need to debug with the build process. And there are more problems today because CRA is not maintained well now.

The tools got much better, it's much easier to just set up a basic Webpack or Vite setup today compared to when CRA was originally created. And the simple configs are much simpler to debug and understand when something doesn't work as expected.


thank you, will keep this in mind if problem arises, maybe the best route would be to reset the build system


I mean, the CRA repo is under facebook org in github


What is cra?



I have been using React at least since 2017 so not a hater; but how many version are we away from elm at this point?

https://elm-lang.org/


React was closer to elm during the times of stateless functions and redux. Since then it's getting further apart from elm.

Redux was kinda of a poor man's elm but it got the right principles. However the JS community hates boilerplate code so, new, more complicated abstractions appeared. Also, it was too easy, with redux, to shoot yourself in the foot.

Since then, with hooks, things are just getting harder and more complicated in my opinion.


Redux had some strange "features" that increased boilerplate without bringing anything worthwhile: mapDispatchToProps (I see it is gone since hooks, I could never find any sensible reason to use it the way authors wanted), global reducer, serializable state, serializable actions.

I once counted how many things you had to do to add new button with new action (it was when class components were still acceptable) - you had to change 4 files in 7 different places. This was completely insane for me. After little fighting with Redux (so I could pass nonserializable actions) I went down to 2 changes in 2 files (to dispatch action and to reduce it).

Redux is better now but I do not think its principles were that good.


Hi, I'm a Redux maintainer. A few notes here:

- It was never necessary to write `mapDispatchToProps` as a function. `connect` always supported an "object shorthand", where you passed in an object full of action creators, and we recommended that as the default: https://react-redux.js.org/using-react-redux/connect-mapdisp... . That said, yes, with hooks we just give you `const dispatch = useDispatch()` and let you use that as necessary.

- The split across multiple files was never _necessary_. Splitting code like `actions/todos.js`, `reducers/todos.js` , and `constants/todos.js` was _common_ (and admittedly shown in the docs), but Redux itself never cared about how you organized your code at the runtime level. The single-file "ducks pattern" ( https://github.com/erikras/ducks-modular-redux ) was proposed very early on and was always something users could do.

- Labeling "global reducer, serializable state, serializable actions" as "not bringing anything worthwhile" seems like a complete misunderstanding of Redux's design and purpose. Redux was created to give you a consistent data flow architecture, and the ability to make it easier to understand when, why, and how your state gets updated. Centralizing state and having consolidated reducer logic means you _always_ know "go look at the reducers" to see what state the app has, what actions _can_ occur in the app, and how the state gets updated for each action that can occur. Serializable state and actions enable the Redux DevTools, which show you the history of dispatched actions, the action and state contents for each dispatch, and the final resulting state after each dispatch. So, the design constraints are fully intentional to give you the benefits that make the app's behavior easier to understand.

Finally, note that Redux usage patterns changed dramatically in 2019, with the release of our official Redux Toolkit package and the React-Redux hooks API. RTK includes methods that simplify all the common Redux use cases: setting up a Redux store with good defaults, writing reducers with simpler immutable update logic (and getting all the action creators generated for free), patterns like async requests / reactive side effects / normalizing items by ID, and even our RTK Query data fetching layer for fully declarative data fetching and caching.

Redux is not the right choice for all apps, and there's a lot of other good alternative tools in the ecosystem. But Redux's design _is_ very intentional, those constraints were put in place to enable the desired benefits, and Redux usage today is much easier thanks to RTK.


The newish `useReducer` is basically redux but tied into react like in elm.


I'm assuming you mean `useReducer` with `useContext`, but note that they are not a replacement for Redux: https://blog.isquaredsoftware.com/2021/01/context-redux-diff...


That article makes a lot of hand-wavy assertion and makes up strange definitions. userReducer, specially with useContext does absolutely replace Redux and provide mechanism for state management. The article is, in short, just wrong.


The main point is here: https://blog.isquaredsoftware.com/2021/01/context-redux-diff...

Context updates all components while Redux and similar state management tools, because they live outside of React, do not. That's the main reason to use true state management tools over context. If you have a relatively small application or you don't care about that, continue using context. The article is also by a Redux core maintainer so you might call that biased but they know what they're talking about, since they're privy to React design decisions much more than regular users.


> Context updates all components.

All the components that consume it. Not the whole tree under the provider.


It is the whole tree, actually. That's one reason I don't use context.


That is simply not true. Only via a Consumer or useContext hook do you subscribe to hooks.

It is well documented and implemented like so.

https://react.dev/reference/react/useContext > useContext is a React Hook that lets you read and *subscribe* to context from your component.

Emphasise mine.


Speaking of Elm, what is the state of that project? Development seems to have slowed down significantly.


Just use CLJS with Reagent, we had memoization out of the box for a couple of years...


I've heard great things about ClojureScript. My only problem is I don't want to have to touch the JVM.


Memoizaition - since over 10y in imba.io. Just sharing.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: