[HN Gopher] A Critique of React Hooks ___________________________________________________________________ A Critique of React Hooks Author : vicarrion Score : 163 points Date : 2020-04-27 14:06 UTC (8 hours ago) (HTM) web link (dillonshook.com) (TXT) w3m dump (dillonshook.com) | ramoz wrote: | React is great at rendering data. It should've stopped there. | roosterdawn wrote: | After using `ember` and the wonderful `ember_data` at | $PREVIOUS_FIRM, I wholeheartedly agree. React is good for what | it's good for, but the community sadly did not stop there. | tannhaeuser wrote: | JavaScript is great at small-scale manipulation of DOM elements | in response to user events. It should've stopped there. | andrewingram wrote: | I mean, I got full marks on the quiz in the article. I had to | think about the code, but no more than if the same had been | implemented as classes. I have been using React for a very long | time though, but the areas where execution order can be confusing | aren't a problem new to hooks. | | One criticism of the article is that it seems to argue that you | lose the ability to provide HOC (and probably render-prop) APIs | if you adopt hooks in your library. But it's fairly easy to | automatically turn those types of hooks into HOCs, so it actually | makes sense to have the hooks API be the primary one. You can't | really do it the other way around, i.e. turn a HOC into a hook. | lpa22 wrote: | I am disappointed with the React team's decision to push | functional components and hooks as the standard way of working | with React. Not sure if the reason is to make React more | approachable to newcomers or not, but in my experience leveraging | the power of the component lifecycle through class components and | decorators is the most fool-proof way to build and maintain large | applications. Particularly leveraging shouldCompomentUpdate for | performance and componentDidMount/componentsWillUnmount for | registering and disposing of component dependencies is very easy | to reason about and scale. | jimbob123 wrote: | It's a different way to do things. You can still use Class | based components to your heart's content. | efdee wrote: | The reason they introduced hooks was exactly that component | lifecycle and decorators/higher order components were found not | to scale well in larger codebases (as experienced by the people | using React at Facebook). | | The useEffect pretty much provides a direct replacement for | componentDidMount/componentWillUnmount. | | I'm still on the fence, but so far it seems to me that using | hooks makes my intent clearer than using the various lifecycle | methods. | tenaciousDaniel wrote: | IMO, we've traded the complexity of `this` with the complexity of | hooks. Maybe I'm weird, but I never really wrote JS that caused | scoping issues, so I never found `this` to be a problem. At the | very least it's a complexity that is internal to the language | itself. Hooks just feel so _weird_ and alien to JS. I find them | very, very difficult to reason about. | | - difficult to reason about _except for a few simple use cases_. | The developer experience is nice if what you 're doing is basic. | But if, for example, you're aiming for 100% code coverage, unit | testing hooks is an absolute nightmare. | efdee wrote: | Hooks weren't invented because of 'this' complexity though, but | rather as a better way to handle reuseable code (somewhat) akin | to mixins. | petilon wrote: | But that took the simplicity away. Everyone that knows modern | JavaScript knows classes. Now they have to learn this alien | concept called "hooks". | | Now regarding reusability: I have been doing UI code for many | many years and I have rarely felt that logic inside UI | components need to be reusable. First move all business logic | out of UI components into model-layer objects. This | eliminates most of the need for reusable logic in components. | Then decompose your mega-components into simpler components. | This removes all remaining need for reusable logic. If you | still have reusable logic inside your component -- this is | very rare -- allow some duplication of code, this is better | than creating monstrous code that nobody understands. | thatswrong0 wrote: | You're only calling it not simple because you're not | familiar with it. I personally think hooks are simpler | despite being different. Everyone knows "classes" but | React's usage of them is not typical and there _are_ non- | standard behaviors about using them that you have to learn | when learning React (because the classes necessarily exist | within the React runtime). Either way you're dealing with | React. | | And on a day-to-day basis for me, there are still plenty of | uses for reusable logic inside of components even after | extracting business logic / creating small focused | components, especially as it pertains to presentation. A | simple example that I use somewhat frequently is a window- | size watcher.. a pretty simple hook that watches the | window-size, re-renders when it changes (on a debounce), | and it provides the current width x height of the window, | allowing the component to use those values to calculate | some view parameters. With hooks, it's as simple as | plopping `const { windowHeight, windowWidth } = | useWindowSize()`. Without hooks it generally requires | wrapping a component with another. | | I've been using hooks basically since they came out and IMO | they're way more in tune with React's programming model | than class-based components. Even if you create custom | hooks for most components, the paradigm still encourages | developers to encapsulate related pieces of component logic | into their own hook-functions rather than spreading that | logic across multiple lifecycle methods. I haven't come | across a single situation where I would have preferred a | class based component. | tenaciousDaniel wrote: | I'll see if I can find the link, but I recall seeing some | references in the official docs, naming `this` complexity as | a key inspiration for looking to hooks as an alternative to | stateful classes. | genezeta wrote: | It's right there in their intro to hooks in the section | "Classes confuse both people and machines" [0]. | | [0] https://reactjs.org/docs/hooks-intro.html#classes- | confuse-bo... | efdee wrote: | That is about a lot more than just 'this' confusion | though. | genezeta wrote: | I was just providing the link. | runawaybottle wrote: | But focusing in on the 'this' criticisms highlights the | general criticisms. They think 'this', or the Class model | is a barrier to entry for React. | | React is a great framework, and super intuitive on so | many fronts, but where it misses, it misses big. To come | to the conclusion that the Class model, a pretty | predictable pattern, is more a barrier to entry, or a | conduit for confusion, is really misguided. | | Just take a look how simple functional components can | take on a quasi Class-like form with lookup maps for | hooks in this particular article. When you advocate for | stuff like this, you are injecting the community with | effectively bad practices. | | The React dev team can not resort to the 'You probably | don't need ________' article in perpetuity. At some | point, they have to say to themselves - 'We probably | don't need to add this to the API'. | efdee wrote: | I agree that the lookup map thing looks like very bad | advice. I can't see a reason why you'd do something like | that. | | On topic, it has been my understanding that the React | team is moving away from classes for a number of reasons. | Not just because it confuses people (although the pattern | seems to create expectations that aren't met due to | Javascript's weird 'this' behavior), but also because it | doesn't have a good pattern for code reuse (as | demonstrated by the lack of mixins that used to be | popular in React's createClass syntax) and also because | it seems to be a suboptimal pattern for compilers. | | That said, I've moved on from class components to | function components with hooks and I can't remember the | last time I thought something would be easier to | implement as a class component, even though it is still | an option to do so. But that is, of course, anecdotal. | petilon wrote: | I am far more confused by hooks than by classes and | 'this'. | hombre_fatal wrote: | `this.foo = this.foo.bind(this)` and then the new feature | of method properties `foo = () => this` vs `foo() { this | }` are constant sources of confusion for people who | aren't well-established in Javascript/this. Not to | mention function() vs arrow functions. | | All exist because of the idiosyncrasies of `this` that | you may be discounting because of your familiarity and | already being over the learning curve that ensnares | people daily. | pier25 wrote: | Also you can't really try to protect JavaScript | developers from understanding _this_. It 's a fundamental | part of the language. | williamdclt wrote: | Disagree. I understand `this`, but I very, very rarely | encounter situations where it doesn't mean the same thing | as Java's `this`. When you work on a full-React codebase, | it just doesn't really happen. We used to have weird | `this` behaviour on event handlers, but arrow functions | and hooks fixed this. | | Not saying it's good or bad, just an observation | grumple wrote: | That complexity was largely avoided by using arrow | functions. | kevinmchugh wrote: | I never had scoping issues around `this` in my react code | (earlier js libraries, yes), but I still love hooks. I find | them more comprehensible and consistent. I love that the API is | smaller. I had to fix a number of bugs caused by the life cycle | methods when I did a react 15 to 16 upgrade a while back, and | it seems unlikely those can crop up with hooks. | city41 wrote: | A big problem with `this` is it is mutable. Dan Abramov has a | nice article[1] explaining why that is a problem and how it | leads to subtle bugs that are common in React apps. Hooks | eliminate this problem, and I would guess this was one reason | they decided to move forward with them. | | [1] https://overreacted.io/how-are-function-components- | different... | jiofih wrote: | That's not a problem with "this", but a self-inflicted | problem from React's chosen model of reusing class instances. | It's a design choice made by them and not a language issue at | all. | city41 wrote: | True, although I did mean my comment in the context of | React. Hooks are basically them rolling back this choice. | brlewis wrote: | > Maybe I'm weird, but I never really wrote JS that caused | scoping issues, so I never found `this` to be a problem | | Either you're weird, or you've been doing JS mostly in the | modern era of fat arrow functions, and fat arrow functions have | succeeded at reducing the confusion from nested functions each | with their own `this`. | tenaciousDaniel wrote: | Even before arrow functions I just never had much trouble. I | had a very consistent way of writing logic. Only ran into | scoping issues a few times. | [deleted] | Saaster wrote: | I feel that with class components I have a really good | understanding of what is rendering and most importantly, when. | componentDidMount, shouldComponentUpdate, PureComponent, etc. | With hooks, it's much more magic. And clarity of rendering is | literally the one thing I want from React. | | We have two projects, one using class components and one using | hooks, and working on the class components one is unexciting, | straightforward, sometimes repetitious, but never confusing. When | writing hooks on the other hand it's constant gotchas; can't do | that here, didn't memoize this, can't call that within this, etc. | fuzzing until it works as Reacts expects. And then the bloody | thing still renders on every frame. Back to the drawing board to | figure out the right magic incantation. Probably memoize a few | more layers, ugh. | throwaway286 wrote: | This is how I feel too, and I'm a confused how the reaction to | hooks is so overwhelmingly positive. I find it quite strange | that we need to set up an eslint rule to make sure our function | arguments are correct, and it will automatically fill them out | if we don't. And I need to memoize so many things! I feel like | I'm not even writing javascript anymore. | pacala wrote: | Memoization is getting me too. I end up memoizing everything, | which is more verbose than I'd like. Perhaps we're missing some | obvious pattern? | abuldauskas wrote: | My only issue with Hooks has been that they are not inputs into | the component. It's a step in the right direction of making React | more functional I would just preferred less magic, personally. | function Component(props, { useState, useContext }) { ... } | | Of course that would break backwards compatibility with the old | 2nd argument being context, so I get why they did it. | frosted-flakes wrote: | That's not the only problem with your approach. It is extremely | common to use the output of one hook in the input of another, | and that's only possible if the hooks exist in the function | body. | abuldauskas wrote: | I don't really understand how this approach breaks what you | are describing. | | All I'm saying is that instead of hooks API being imported | from React at global scope it could be provided as inputs | into the components directly. They would still exist in the | function body as you put it. | frosted-flakes wrote: | Oh, I thought you meant that the hooks would be _called_ | there, which was one of the many alternative proposals made | after hooks were announced. | | In any case, it still wouldn't work because hooks are | composable. You can create your own custom hooks outside of | components which can be used as if it was one of the | primitive hooks. That's not possible if the primitive hooks | can't be accessed outside the component scope, unless | they're passed in as parameters every time the custom hook | is called (and that would be a right pain in the backside). | rglover wrote: | From what I've learned using them, hooks are a tool like anything | else--pushing one method as "the" way means that you make a lot | of poor engineering decisions. | | Hooks are like a screwdriver; great for simple stuff when you | want to reduce code overhead. | | Sometimes you need a power drill, though, and classes and the | old-school lifecycle functions are wonderful for that. | contigo wrote: | IMAO hooks are just a dirty hack, but sold very well. Internally | in React the state of a hook is being kept and updated when you | call the set function, kinda similar to vtables and context in | OOP. There is no other way to do this AFAIK. It only mimics | functional programming, and that's why you see the restrictions | about hooks, you cannot use them outside React, cannot nest, | etc.. | dcre wrote: | An important point I don't see being made in the article or the | comments is that hooks are meant as a more faithful (or at least | less misleading) representation of what was going on under the | hood in React already. | | The problem with the JS class representation is that people | already understand what classes and instances are, and that leads | to incorrect inferences about how React is working. In addition | to better-organized code, the hooks abstraction is partly aimed | at preventing people from making those wrong inferences. This | also explains why they are uncomfortable compared to classes and | functions -- the point is that was a false comfort because those | representations are misleading. | | Dan Abramov calls hooks a "missing primitive": | | "Why are these models insufficient to describe React? "Pure | function" model doesn't describe local state which is an | essential React feature. "Class" model doesn't explain pure-ish | render, disawoving inheritance, lack of direct instantiation, and | "receiving" props. | | What is a component? Why do you start writing it one way and then | have to convert into another way? Why is it "like A but also like | B"? Because it's neither. It's a thing of its own. A stateful | function with effects. Your language just doesn't have a | primitive to express it. | | That's what Hooks are. Those missing primitives. They are | library-level but conceptually they are part of the "React | language". Hence the language-like "rules". | | They _could_ be syntax. They _would_ be in Eff or Koka. But the | benefits are not worth the friction it creates in JS. " | | https://twitter.com/dan_abramov/status/1093696560280596491 | | https://twitter.com/dan_abramov/status/1093697963350810624 | | https://twitter.com/dan_abramov/status/1093698629708251136 | traderjane wrote: | > A stateful function with effects. Your language just doesn't | have a primitive to express it. | | I wonder what about generator functions? | lhorie wrote: | Yep, there was even a library making the rounds recently that | leverages them: https://crank.js.org/ | hombre_fatal wrote: | Another example: Redux Saga has been using them in React | for a long time. https://redux-saga.js.org/ | dcre wrote: | I don't see how generators would change anything here. "with | effects", "stateful", and the integration between the two are | all equally important in the statement. | orange8 wrote: | There are two different concepts as I see it, please | correct me if your definitions differ. | | "stateful": A function that has state, i.e. can store data | | "with effects": A function that modifies data outside its | own scope | | Normal JS functions (as opposed to arrow function) already | do this: | | function foo(){}; | | foo.state = bar; | | Generator functions take it a step further, where the | function remembers internal state between calls. | williamdclt wrote: | Well generators are a good primitive to represent | "stateful" "functions" "with effects". The concept of | hooks, which somehow give the control back to React to do | something, map marvelously to react. | | I'd be surprised if generators didn't come into React at | one point or another | Saaster wrote: | As a user of a library, I don't really care how it works. Under | the hood it can be arbitrarily complex or simple, and please | feel free to change the implementation weekly for all I care. I | care very deeply about my own components, when they render, | what causes them to re-render, and that I can control and | reason about when they re-render. Also, stability of API (in | number of years) is way more important than new whiz-bang | features. | lhorie wrote: | It's interesting that the original appeal of React was that it | was "just a view library", but now apparently it's more like a | "language". It really shows the biases of the maintainers (the | "just a library" thing being a philosophy I liked from vjeux, | and the "language-likeness" being very obviously a heavy | influence from sebmarkbage). The thing w/ "language-ness" (as | opposed to "library-ness") is that additions and changes to a | language tend to become more and more difficult to make over | time because semantics deeply affect everything in the system, | whereas well designed APIs in a library-oriented approach can | be well encapsulated. | | I've said for a while, for example, that throwing promises for | Suspense is using up "escape hatches" in JS. The rule of hooks | is another one of those. Eventually, the React team will run | out of escape hatches to implement "React language" semantics | around the real JS semantics, and I suspect at that point | sebmarkbage will move on to create a new view framework (as has | been the case w/ e.g. sebmack and babel/rome, Rich Harris and | ractive/svelte, etc). | | It'll be interesting to see if whoever steps up to maintain | React at that point will be able to grok its internal | complexity, and to see how the community reacts to a rift when | their favorite view library team pushes for one vision but the | moved-on "rockstar facebook engineer" pushes for a different | vision. | | EDIT: fixed name confusion (thanks, swyx!) | gotofritz wrote: | > It'll be interesting to see if whoever steps up to maintain | React at that point will be able to grok its internal | complexity, and to see how the community reacts to a rift | when their favorite view library team pushes for one vision | but the moved-on "rockstar facebook engineer" pushes for a | different vision. | | Kind of what is going on with Node / Deno... and like the | chap who quit the Angular 2 team to start Aurelia hoped would | happen to him (sorry buddy!). My guess is that he'll find out | that there is more to a framework than rockstar developers. | Like Facebook backing, or like UX designers being in love | with your library because it reflects their approach to | problem solving. Like CRA, hot module reloading and all that | jazz. These are all things that put React where it is today | searchableguy wrote: | isn't react created by jorde walke? | csmiller wrote: | I thought Jordan Walke created React, not Sebastian Markbage, | in which case he already moved on (to ReasonML) | kiliancs wrote: | Was it sold as "just a view library" from official sources? | | I understand "just a view library" might have been used to | contrast it to full framworks that dictate a lot more than | React, but it's important to note that the key React feature | compared to other view libraries is precisely that it's not | "just a view library": state is at its core. | | It's hard to disagree with the the pain of React having to | leave the comfort of plain idiomatic JS to better fulfill its | goal, but to me React's efforts are in a way an experiment to | find some primitives that should be baked into JS engines to | allow for these mature, fine tuned experiences without | putting the burden on the library. | lhorie wrote: | > Was it sold as "just a view library" from official | sources? | | Yes, the "V in MVC" term came straight out its main page: | | > JUST THE UI | | > Lots of people use React as the V in MVC. Since React | makes no assumptions about the rest of your technology | stack, it's easy to try it out on a small feature in an | existing project. | | https://web.archive.org/web/20140321012426/http://facebook. | g... | kiliancs wrote: | Thanks for finding that! Yes, it seems like this way of | seeling it could cause false expectations. It is still | true, though, that "React makes no assumptions about the | rest of your technology stack, it's easy to try it out on | a small feature in an existing project". | swyx wrote: | > and the "language-likeness" being very obviously a heavy | influence from sebmack | | just a minor correction, you probably mean seb markbage, who | works on React, not seb mackenzie, who made Babel and now | Rome and i dont think was ever on the React team. | | i agree that when seb markbage leaves, it will be a big test | of React's legacy. I've called it the "Ship of Theseus" | moment for React. | e12e wrote: | > It's interesting that the original appeal of React was that | it was "just a view library", but now apparently it's more | like a "language" | | Well, it was prototyped in standard ml first[1], wasn't it? - | then ported/re-implemented (shoehorned ;) into plain js. | | So some things that sml has, and made sense in sml, had to | become part of the library/language/framework that is react? | | Later came reasonml (a ocaml dialect) which is a lot closer | to sml than js - and I think the state handling reflects | that, like the readme for reasonml variant of redux: | | https://github.com/reasonml- | community/reductive/blob/master/... | | "The code behind Reductive is incredibly simple. The first 40 | lines include the entire re-implementation of redux. The next | ~40 lines are a re-implementation of the react-redux library | (without the higher-order component connect style | implementation)." | | In a sense, react has always been a design pattern - and a | library to support/enable that pattern in Javascript. | | [1] https://www.reactiflux.com/transcripts/jordan-walke#come- | ide... | bobblywobbles wrote: | This is why I avoid hooks. I design my components to use state | and I find hooks to not fit well in my applications. | jwr wrote: | ClojureScript user here, with a big SaaS app using React, | developed over the last 4 years or so, using the excellent Rum | library, https://github.com/tonsky/rum. | | It seems to me that React Hooks, like so many things in the | JavaScript world, solve a problem I do not have. To this day, | despite being a heavy user of React, I don't even fully know what | they do. I've read the "Motivation" section of the React Hooks | Intro, and it seems that I have none of the problems they | describe: I can (and do) easily add stateful logic via Rum | mixins, and that logic is reusable across components. Also thanks | to Rum mixins, complex logic is understandable and does not get | all thrown into a single 'componentDidMount' function. As to | "Classes confuse both people and machines", I find it hard to | relate to this problem, because I don't really see any classes. I | work with components that have a render function and mixins, and | if you don't use any mixins, a component looks just like a | function. | | This tends to be a recurring theme: every once in a while I read | an article about JavaScript and React, and I can't even relate to | the problems, because they do not exist in my world. Another good | example is hints on how to optimize apps to avoid excessive re- | rendering, something I get for free with ClojureScript and | immutable data structures (you can always quickly tell if two | data structures are equal and avoid rendering). | onion2k wrote: | You've solved the problem that hooks solve by using Rum mixins | instead, and you're confused why you don't need hooks? | iLemming wrote: | Have you actually used Clojurescript with React? Just any | cljs library - Reagent, Rum, Re-frame, Fulcro? Maybe try it, | perhaps then you'd understand why Clojure developers often | get confused what problems every new hype cycle in JS/TS | world is trying to solve. Because Clojure idioms often nicely | turn them into something you don't have to worry about at | all. | Scarbutt wrote: | Yeah, that's why rum recently added support for hooks... | iLemming wrote: | Rum and Reagent added support for hooks mainly for | compatibility. Never needed them before. | deckard1 wrote: | Hooks elucidate everything I've felt wrong about React, but have | not been able to put my finger on it until recently. | | Hooks reveal two major things with React: | | 1) React developers did not understand the component paradigm | that they originally went with. If they did, then they would | understand how silly it is that components cannot reuse logic. | This was an entire debate many years ago. Composition vs. | inheritance. You don't need to throw out classes or objects to | get reuse. | | 2) React developers do not understand functional programming. I | could write an entire essay on this. But it should suffice to | say, FUNCTIONS DO NOT HAVE STATE. What React hooks introduce has | more in common with dynamic scoping, of older LISPs. It | fundamentally breaks lexical scoping, which is _incredibly_ | important for understanding code flow. You have to be constantly | aware of when it 's safe to use certain variables and the | implications of using variables in certain scopes now. In 2020!! | This is INSANE. | pacala wrote: | Huh? You can treat state as arguments to your function. For a | given function evaluation, the state is stable. The fact that | state can be changed during event handling is 100% irrelevant | to the evaluation. There is no dynamic scoping. | throwanem wrote: | Who says functions don't have state? Referential transparency | requires no such constraint; it only requires that state not | leak into or out of a pure function save through its arguments | (inward) and return value (outward). Beyond that, what they do | within the space of their own lexical scope and the lifetime of | their call stack frame is entirely their own business. | | I'm familiar with dynamic scoping via Emacs Lisp. I have yet to | encounter anything like it in React, and it'd be surprising in | any case to encounter dynamic scope in Javascript, a language | which does not even support it. The closest I can come to | understanding what you must mean here is to think you're very | confused about how React props work, but that doesn't seem | likely either - I can hardly imagine someone having such an | evidently strongly held opinion about something, and having | that opinion turn out to be based on a fundamental | misunderstanding of the subject. | | Would you mind explaining in some more detail the issues you | see with React functional components? You mention having an | essay's worth of material, and while that's probably more than | we need to support a discussion, perhaps you'd be so good as to | boil it down to a few points with a little more substance to | them than "React developers don't know what they're doing" and | "this is insane". | ng12 wrote: | > But it should suffice to say, FUNCTIONS DO NOT HAVE STATE | | It's funny you say that: useState is the same model functional | languages use to handle mutability. | | https://docs.racket-lang.org/reference/boxes.html | hombre_fatal wrote: | > they did not understand | | > they do not understand | | > This is insane | | This sort of post that asserts that nobody understood or put | delicate thought into something is just pompous and lacks | intellectual curiosity. | | At least respond to their rationale. In doing so, you'll find | that everything is just trade-offs. | | btw Dan Abramov is great to follow on twitter. He often | responds to criticism and clarifies React decisions and links | to good blog posts. If you use twitter it's a nice way to get | polite, bite-sized wisdom about React and Javascript. At the | least you'll realize how much good thought goes into React. | jiofih wrote: | It fares well next to all the other comments saying this | article is "pure whining". | petilon wrote: | > _how silly it is that components cannot reuse logic_ | | It may be that your component is too complicated. Components | should only have UI code. First move business logic out of the | component, into your model layer, and make it reusable there. | This step will eliminate most of the need to reuse logic in | components. If you still have logic inside your component that | you want to reuse consider restructuring your component into | multiple simpler components. | parley wrote: | > React developers do not understand functional programming | | As some sibling comments note, this is not a fair conclusion to | draw. And not that it disproves your statement, but Reacts | original creator Jordan Walke wrote the first React prototype | in SML. Not understanding functional programming is not on the | list of things I would ascribe to him. He's a smart guy. | | On a slightly different note, I'd recommend anyone try out | Reason. It's slowly maturing and can be a real joy, at least | compared to JS/TS. | nammi wrote: | Do you have any good resources for getting started with | Reason? I've tried a couple times, but it seems like there's | a schism between https://reasonml.github.io/ and | https://reasonml.org/ | psmyrdek wrote: | RE: 1) "it is that components cannot reuse logic" - +1 to this | - recently I re-watched original hooks talk by Dan Abramov and | was not able to finish it with conclusion different than "you | guys really fix issues you invented before". Class-based | components and reusability of logic is something that existed | years before React, and probably will exist years after React. | Even this concept of Dependency Injection and Services that | Angular is still on proves that there-are-solutions. There are | solutions for reusing logic between classes. Thing that bothers | me the most is not that there's something wrong with fixing | your own issues, but the fact that developers outside React | Core Team start to think that "well, you cannot reuse logic | between components". | ng12 wrote: | Angular does not have a solution for this as far as I know. | It's not about re-using logic. It's about re-using _reactive_ | logic that ties in to your component 's lifecycle. | spaceribs wrote: | I'd argue Angular does, in the form of RxJS. | arianvanp wrote: | The "idea" that react hooks try to implement is very common in | FP languages though. It has a lot of parallels with extensible | effects; which is a pure, functional embedding of the idea of | hooks | draw_down wrote: | I don't think this is a great critique, simply because the pain | I've encountered using them isn't mentioned here. The | incompatibility with class components is what it is, they're | different programming paradigms that you have to choose between. | If your library leaned heavily into HOCs, that was an unfortunate | choice and I'd recommend making a new library because HOCs were | always unwieldy and had problems with composition. Nothing to do | with functional components or hooks really, just a very heavy | pattern that can typically be done better with another approach | like render props. | | I guess I see a lot of this as evolutionary. It's unfortunate | that there has been so much change, and the timing might not be | great for some projects, but I would not prefer a world where I | was still writing and using HOCs and class components. | | In my day job I work on a pretty old (in React years) project, | and we haven't had trouble writing new code in a functional + | hooks style. Still plenty of class components abound. | twic wrote: | I learned about Crank today: | | https://crank.js.org/blog/introducing-crank | | Crank itself is interesting, but what's relevant here is the | broader critique of React there. | wk_end wrote: | This is really compelling - thanks for linking it. Is there a | downside here? Has React responded at all? I don't hate hooks, | but using async + generators like this looks so obviously | better and more intuitive here; like such a clearly great, | simple idea that I'm embarrassed I didn't ever think of it | myself. | runawaybottle wrote: | A lot of times I just use a simple React class. The author's | lookup map to return a lookup of other hooks, yikes. A class | component would probably solve that in a more predictable way. | | Don't feel dirty for doing things simply. If your functional | component has entire lookup maps for hooks, it's probably too | complicated as a standalone functional component to drop hooks | in. | efdee wrote: | It's hard to reason about without an actual real-life use case, | but the lookup thing he's doing looks extremely convoluted to | me. | jiofih wrote: | Once you start using Context everything has to become a hook | to be able to consume it, I bet that's what's goin on there. | WorldMaker wrote: | Right, I'd be curious to know a lot more details of the real- | life use case that inspired that. My gut feeling says that | there's maybe a state machine of some sort which could | possibly be split into a sequence or maybe hierarchy of | smaller components, but it's hard to tell specifically what | the alternative might be without more details on why they | thought a lookup table might be useful. | draw_down wrote: | Agree, I don't know what is going on there but it sure smells | like something you shouldn't need to do. | lucideer wrote: | The reaction to react hooks has been (as far as I've seen) a | little too positive, so I was looking forward to read a genuine | critique. | | However, I'm disappointed. | | In reverse order: | | > _5. They Complicate Control Flow_ | | A set of contrived examples, within which the only genuinely | confusing part is not related to React at all. It's Javascript's | object non-equality ({ multiplier: 5 } !== { multiplier: 5 }) | | > _4. The Rules of Hooks Limit Your Design_ | | This is an interesting section but seems to point to a pattern | that would lead to serious issues given any library/paradigm. | It's criticising the Rules for their inflexibility, but in this | instance they're _helping_ you by pointing out the pitfalls of | your approach, and encouraging you to rethink it. | | An alternative way of looking at it is that it's again (like in | 5) bemoaning Javascript's object inequality which is prevening | the memoization here. | | The other 3 bullets are pretty silly "boo new things" issues that | are common to migration to any new API. | dgritsko wrote: | Agree, "More Stuff to Learn" isn't really a critique of hooks, | it's a critique of _learning_. | nicoburns wrote: | Yeah, I don't really get this criticism in regards to hooks. | I think it took me maybe an hour to learn them. That's | basically nothing. | lucideer wrote: | I've never* used hooks and I only got 1 question wrong in | the author's Google Forms quiz (would've been 2 wrong, but | bullet point 4 had already signposted the object equality | gotcha). | | So there doesn't seem to be a huge amount to learn in hooks | as far as I can tell. | | * I am an experienced React developer but haven't had much | opportunity to work with it in the past 2 years. | azhu wrote: | I initially had a few, but after making sure they weren't just | learning curve exasperations in disguise, I realized they all | boil down to that they should've just started out with this and | never had any class components. | | I often see developers mix up classes and functional components | with hooks in abominable ways, and every pitfall to hooks I can | find just boils down to improperly brackish OO class model | polluted thinking. | joonhocho wrote: | I was skeptical towards hooks when it was first introduced. I was | hesitant to use it. Then, I used it for a few components in my | projects. I realized how much simpler my code looked, and | migrated completely to hooks. No regrets. | ttty wrote: | Hooks are magic with new rules that are different from regular | JavaScript. They don't follow the regular flow you'd expect it | would. Requires devs to think a lot about hooks to make sure | something is messing them up. Also needing eslint to make sure | your code is ok, is a boy flakey. | | Hooks it's like learning a new language pretty much, which is | only useful for react. I'm using them because of lack of better | things. | frosted-flakes wrote: | Once you understand that function components aren't simple, | contained functions but rather components that exist in a | parent scope (React) and that React actively manages them, it's | not magic at all. Also, you don't need ESLint; the rules are | pretty simple. | lpage wrote: | > The problem with learning about hooks is that they're not | generally applicable knowledge about computing or programming. | | That's true of the hooks API specifically, but not true of the | underlying abstraction. Hooks are (informally) algebraic effects | - one of the coolest and most general abstractions for inspecting | and manipulating a program's control flow [1, 2]. Algebraic | effects are still somewhat niche and most programmers haven't | encountered them in name or in practice, so in that regard, hooks | are actually one of the fun cases when learning a new API is mind | expanding. | | [1] https://github.com/ocamllabs/ocaml-effects- | tutorial#1-algebr... | | [2] https://overreacted.io/algebraic-effects-for-the-rest-of-us/ | mrozbarry wrote: | One thing that baffles me is that no one has brought up that | hooks don't have an obvious context. | | For instance, if I have a single app and component, and use a | hook, I understand that the hook and app have some sort of | implicit connection. | | But what happens when I have two distinct react apps on a page - | does that break the ordering that hooks require? How does a hook | have any affinity to the app, or does that even matter? | | I'm sure looking at the code will cause a "oh, I get it" moment, | but that doesn't mean it's obvious to anyone just picking up | hooks. | | Honestly, I think hooks are fine, but I'd almost prefer a | signature like `const MyComponent = (props, { ...hooksHere })` so | there's at least a false affinity between the application and the | component. | gotofritz wrote: | > hooks don't have an obvious context. | | I mean, that's the whole point of hooks... they get the context | of whatever host function scope they are in. That's why the | 'reusable logic' spiel. So if you create a useLocalStorage | hook, for example, you can then plug it into any function | component and it will use. It's as if each function was an | invisible class, with an invisible this.state | azhu wrote: | All of this reads akin to someone criticizing an apple for not | being an orange. Every point is an intentional design decision. | Learning new things is necessary, leaving class syntax behind was | a choice, and imposing limits on (controlling) application design | is the point of libraries. | | The team is pushing a functional declarative pipe method of | building UI applications where things are built using a straight- | line series of composed functional transformations. Personally, I | think supporting this method with the hooks model of handling | side effects is an improvement over everything else that exists | in "roll your own" UI library land. I find these style libraries | more enjoyable to build with, more expressive, and better suited | to building things where you need finer grain control than | template style libraries like Vue, which provide a stronger | degree of predictability and ease of immediate use. | | That's the thing -- it's a balance. Hooks add a nicely considered | and balanced degree of order to the otherwise intentionally | uncontrolled-so-you-can-do-the-controlling programming model of | React. React identifies as the advanced lego set with the smaller | more numerous blocks that you can build the cooler stuff with, | and as such will always have a certain threshold of complexity. | lhorie wrote: | > imposing limits on (controlling) application design is the | point of libraries | | That's the point of _frameworks_. It's very ironic to see this | being said in defense of React, given that its original appeal | was precisely the opposite stance (i.e. React was "only the v | in mvc", in response to the notion that frameworks of the time | were imposing). | jiofih wrote: | You didn't actually counter any of the authors' points. | | This wonderful _functional declarative pipe method of building | UI applications where things are built using a straight-line | series of composed functional transformations_ can really suck | in real world applications as he tries to demonstrate. Anyone | building with hooks now can relate to hooks bringing _disorder_ | to the codebase. | | Has your experience been different? How did you avoid the | pitfalls mentioned? | ng12 wrote: | Well #2 isn't really a pitfall, for starters. I have a new | feature that solved a problem I had but I can't use it in the | code I wrote before I had it without refactoring? I don't | think that critique really has anything to do with Hooks, | just software development. It's also basically a rephrasing | of #3. | pacala wrote: | 1. It's not more stuff to learn, it's _different_ stuff to | learn, arguably less. Learning Components is not a | prerequisite for learning Hooks. Or perhaps I missed the | memo, as I 've built an app using Hooks, and still haven't | need to learn what 'componentWillMount' is supposed to do. | | 2. Don't mix Components and Hooks. | | 3. Agreed, change is hard. It's also the only way to avoid | stagnation. In the long term, change wins. Or else we'd be | programming in JS1995. | | 4. Insufficient example. What is the business case for a | memoized hook returning hooks? Perhaps there is a simpler | design, can't comment. | | 5. There is no global control flow. There is only per | function component control flow, which proceeds from top to | bottom. Possibly preempted by a hook/hookfn execution, if my | early learning curve is to be believed. Which shouldn't | matter if one is thinking in terms of 'pure functions | returning jsx', as preempted functions do not return, thus | have no observable effect. | | Tip: Only change hook state from event handlers, never from | render function code. | viklove wrote: | > In the long term, change wins. Or else we'd be | programming in JS1995. | | Change for the sake of change is not a sound argument. | | The thing about hooks is they don't enable a single thing | we couldn't already do with HOCs. They are also much harder | to read, because stateful logic is now just sprinkled | around your render method rather than being isolated to | places you know to look for it. I won't be using hooks | ever, as far as I'm concerned. | pacala wrote: | Of course. | | * "A Critique of React Hooks" | | * "A Critique of the Change Costs Induced by React | Hooks". | | Objections to React Hooks are stronger if they don't | invoke change costs as the primary three concerns. | runawaybottle wrote: | He/she gave a very valid critique of state being jammed | into your render method, vs state being handled in a | predictable pattern in Class components. | | And lastly, let's not minimize change-cost. In the real | world, it's a cost. We're all willing to pay it if it's | necessary, or affordable, but not because someone showed | up and said 'change please'. | Scarbutt wrote: | Unless you learnt react from non-official sources, you | can't avoid learning components because they teach them | first. | pacala wrote: | You'd be surprised. The only deeper dive into Components | is https://reactjs.org/docs/state-and-lifecycle.html of | the "Main Concepts" section, which I skipped in favor of | https://reactjs.org/docs/hooks-state.html of the "Hooks" | section. Haven't got to "Advanced" yet, hope to stay | clear of that. | acemarke wrote: | The React team is working on rewriting the docs to focus | on function components and hooks first, as of this | quarter: | | https://www.reddit.com/r/reactjs/comments/g2pda4/function | al_... | pier25 wrote: | > In the long term, change wins | | Yes, but how long is long term? | | jQuery hasn't radically changed its methodology in almost | 15 years. | chadlavi wrote: | > so much to learn | | it's almost like software development is a highly skilled | technical profession that takes years to master? | a-priori wrote: | I've been using hooks full-time for the last year or so in a | _very large_ React code base (one of the largest in the world). | None of these so-called problems are real in my experience. | | The first point is just whining about not wanting to learn new | things -- we've on-boarded many new people onto our team in this | time, and hook-based code is the easiest to understand. It's the | old class-based components that are hard, and the most | experienced team members work there usually to rewrite them as | functional components. | | The second point is only sort of true. They can interact with | class-based components in a parent-child relationship. That's | enough to gradually migrate your application towards hooks: any | time you want to make significant changes to a component, rewrite | it. | | The third point is not a problem in my experience. Yes, we have | rewritten some of our internal libraries as a direct result of | hooks being available, not because the old ones didn't work but | because we now had the tools to create a _much better API_ and | took advantage of it. | | The fourth point makes no sense to me. If you need to use | conditions like that do something different, e.g. put the | different cases ("a" vs "b") in different child components and | render the appropriate one. Any programming paradigm has rules | around it, and this is no different. | | My response to the fifth point is "don't depend on control flow". | You should be robust to evaluation order so it doesn't matter the | exact order that React executes your code. If you have a | execution order dependency in your code it will be highly | brittle. | gregkerzhner wrote: | In my experience people abuse react components by making them | too big with too much functionality. If you have a bunch of | hooks tied together in a brittle way, thats not the hooks's | fault. It's a good sign that you need to refactor your | component into smaller sub components or move functionality out | of components all together into redux or some other non UI | related code. A big component with lots of logic will always be | a liability whether it's hooks or classes because it will mix | presentation with business logic and will rarely be well | tested. | sibeliuss wrote: | It's unreal that in React I have to deal with occasional infinite | loops now because of hooks. Sure, React catches the loop cycle so | things don't totally freeze but I don't recall ever having to | deal with this before them. Weird, unexpected reference issues, | missing dependency accidents requiring linters to prevent, | strange programming patterns, a team member having to write a | terrifying novel like https://overreacted.io/a-complete-guide-to- | useeffect/ for something that was never really a problem before. | The list goes on and on. | dgritsko wrote: | You could easily wind up with an infinite loop without hooks | (for example, by calling `setState` in `componentDidUpdate`). | jiofih wrote: | That would be trivial to spot. Not the case with hooks. | [deleted] | s-km wrote: | >It's unreal that in React I have to deal with occasional | infinite loops now because of hooks. Sure, React catches the | loop cycle so things don't totally freeze but I don't recall | ever having to deal with this before them ... missing | dependency accidents requiring linters to prevent | | Infinite loops and missing dependencies are/were issues with | `componentDidUpdate`/`componentWillUpdate` and | `componentDidMount` as well, though. On the plus side, you now | have a linter which can both point out these errors and | automatically fix them for you. I agree that the whole thing is | a bit leaky and dumb though, but there's no way to fix that | without introducing some sort of compilation/optimization step | and afaik the React guys aren't really considering that at the | moment. | | >Weird, unexpected reference issues | | Not sure I've run into this before. Do you have any examples? | | >strange programming patterns, a team member having to write a | terrifying novel | | The first bit seems like personal preference or something, not | sure what you're referring to as strange. The `useEffect` novel | exists because a ton of people had built up their (incorrect) | mental model of how React works with lifecycle methods and were | making mistakes or running into unexpected behaviour because | they assumed `useEffect` was the _exact_ same thing as | `componentDidMount`. | sibeliuss wrote: | Reference issues: | | 1) Needing an advanced understanding of closures. Not always, | but sometimes. That "sometimes" is often unintuitive, | requiring weird solutions like useRef. Good luck beginners. | | 2) Things like updating reducer state by using a spread | object, which creates a new object which can then send a | system haywire. Seems fine, and is mostly fine in most cases, | but hey, oftentimes not fine, and why that's so is not always | clear. So then there's memoization, and useCallback and all | of these safety checks -- each with their own dependencies | array that need to be checked. It's really too much tbh. | There are lots of solutions out there that use proxies to | check this stuff; React should have baked that into the core | and completely removed that responsibility from the user | unless they wanted to opt-in micromanage performance of their | code. | ng12 wrote: | > Things like updating reducer state by using a spread | object, which creates a new object which can then send a | system haywire | | This is what you should be doing and not doing this seems | more likely to cause problems. Do you have an example? | exogen wrote: | The problem before was that your class component was not | updating correctly and rendering stale & out of sync data. If | it were updating correctly, it would have had the same infinite | loop problems. | ng12 wrote: | Exactly this. Class components let you cheat and easily write | components that were broken if a prop was unexpectedly | updated. Hooks will surface this immediately. | [deleted] | stevebmark wrote: | Hooks have unlocked so much power in React but still deserve | critiquing. However I think the author only hinted at the major | complaint I have about hooks, which is that it's no longer | Javascript. It's not a function, it's sort of like type system | magic. Hooks can't be nested, order matters, can't be | conditionally called, and you have to understand trickier | memoization to avoid bugs. It also isn't portable knowledge to | other systems, like vanilla Javascript is. React is great because | it's vanilla Javascript, expressions all the way down, and | lifecycle methods, which everyone is used to. Hooks are a new | non-vanilla-javascript paradigm with special and sometimes tricky | rules. Other than, there's no reason to write React unless you're | using hooks, and I wonder what the next major paradigm shift will | be. I look back on all our HOCs and function as children and | shudder compared to how easy it is with hooks. | vosper wrote: | > I look back on all our HOCs and function as children and | shudder compared to how easy it is with hooks. | | If by "function as children" you're referring to render props, | personally I was really happy to see that short-lived fad die | out. I don't think render props made things simpler. | | Now if we can admit we never needed Sagas just to do some data | fetching maybe we can burn that stalled-out old bandwagon, too | :D | | (Sagas are a powerful pattern, I'm sure someone here is about | to reply about how they're making good use of them. But I'd bet | 99% of people using the redux-sagas library could be doing | something simpler). | stevebmark wrote: | I have never fundamentally understood sagas and I've tried a | few times. I'm able to wrap my head around redux-loop though | https://github.com/redux-loop/redux-loop | orange8 wrote: | > the major complaint I have about hooks, which is that it's no | longer Javascript | | Are you saying that hooks are implemented in a way that needs a | compiler (e.g. like CoffeeScript or TypeScript) for them to | work? I've always assumed they were implemented using closures | or a similar pattern. | lucasmullens wrote: | It is JavaScript, but it doesn't feel like JavaScript. What | looks like a pure function isn't actually, and can do a | different thing depending on where and when you run it, all | hidden in some magic within the React library. | orange8 wrote: | JS is one of the most un-opinionated, flexible language | around, I do not believe there is _a one true way(tm)_ of | doing JS. For example, React and Angular have very | different approaches (functional vs OPP) on how to JS. | | I do agree that having something do a different thing | depending on where and when can be counter-intuitive. | untog wrote: | > React is great because it's vanilla Javascript | | What about JSX? It's very useful but it's also an absolutely | huge departure from vanilla JavaScript and hides a fair amount | of complexity behind what your code is actually doing. | lucasmullens wrote: | > an absolutely huge departure from vanilla JavaScript | | Doesn't it just convert to React.createElement? I wouldn't | call it absolutely huge. | frank_nitti wrote: | By this logic, what could ever be considered "huge" | departure? Any new language construct "converts" to | something lower level unless that language is a set of | assembly instructions. I mean, Elm converts to vanilla JS | but few would say it's a small departure from it. | TomMarius wrote: | For example Angular templates, stuff like Razor in .NET, | etc? | stevebmark wrote: | My mental model of JSX is that it's vanilla Javascript, and | it's helped me appreciate trying to write more expressions | and less statements. Like JSX isn't getting transformed into | some weird different control flow, it's just a nicer way to | write the same expression. And DSLs are a good general | computer science principle. Hooks don't seem quite as general | of a concept to me as a really well thought out DSL that has | a minimal surface area but still turns out to be super | useful. | TomMarius wrote: | The JSX is just a bunch of function calls, all the complexity | is in React the library - you can do a very light JSX to DOM | library with zero of that complexity. | sibeliuss wrote: | <Foo bar="baz"/> = Foo({ bar: "baz" }) | ericmcer wrote: | Feels like the author is someone who really sunk into the | composed higher order component style of writing React. As | someone who has coworkers who loved spreading logic into | 'composable HoC' that only end up being reused 1-2x, I welcome | hooks. | | A single component wrapped by 3-4 HoC that each do trivial tasks | always felt like mental strain rather than a helpful abstraction. | My favorite was HoC's that added class component functionality to | function components... just use a class. | mikewhy wrote: | Ah, I used to be on this side of the fence. Now I've learned to | love hooks, and aced the test (except for the last, extra BS, | question). | | Now the two issues I have with hooks still nag me in the back of | my head, but are easy to get over: | | - `useCallback` still makes new function references that wouldn't | happen in class-based components. as someone who starts out with | `class MyComponent extends React.Purecomponent`, that bugged me. | | - easily access old props after updating. I built my components | with something like `useEffect`, where mounting was considered | "changing props from null to _something_", and updating was like | normal: class MyComponent extends React.Component | { componentDidMount = () => { | this.handlePropsChange(null, null) } | componentDidUpdate = (oldProps, oldState) => { | this.handlePropsChange(oldProps, oldState) } | handlePropsChange = (oldProps, oldState) => { if | (didPropChange('userId', oldProps, this.props) { // | now we know that props.userId changed, but also have access to | `oldProps.userId` in case there's any cleanup that needs to | happen. } } } | | I know this is possible with functional components / hooks, but | it was nice to get this stuff "for free". | jasonkillian wrote: | Hooks are great for simple use cases like `useState`, | `useContext`, some uses of `useRef`, etc. and can make the code | easier to read and reason about (while conveniently working very | well with TypeScript). | | The rules do start to get really tricky though with complex use | cases of `useEffect` and multiple levels of nested hooks, and | implementation problems are often not easy to spot or debug. | | Dan Abramov has written a lot about the philosophy of hooks[0] at | his site overreacted[1], I'd love to see a 'retrospective' write- | up from him or another React team member about what they think | the success and failures of hooks have been so far and if there | are any changes planned for the future! | | [0]: https://overreacted.io/why-isnt-x-a-hook/, | https://overreacted.io/algebraic-effects-for-the-rest-of-us/, | https://overreacted.io/a-complete-guide-to-useeffect/ | | [1]: https://overreacted.io/ | luwes wrote: | Hooks are nothing new, it's just repackaging of | | https://github.com/dominictarr/observable | https://github.com/adamhaile/S | | Mobx and Vue use the same technique for running computeds. | | As does Solid and Sinuous, etc... | jiofih wrote: | Hooks are much more a reimplementation of the component | lifecycle; receiving a change stream is only one of the use | cases and has very little resemblance to observables, except | that they trigger a re-render "automatically". | psmyrdek wrote: | There's yet another valuable hooks critique that I recommend you | to read - https://typeofweb.com/wady-react-hooks/ (Use Google | Translate to convert Polish to English) | lioeters wrote: | Hahah, this is good. | | > React, like socialism, perfectly solves the problems that it | created. | andrewrothman wrote: | Good critique. I agree about control flow and memoization. I tend | to run into issues every now and then with memoization and hook | "dependencies", but I'm getting better at it. | | I think 1, 2 and 3 aren't really great arguments. There's always | more to learn, and it seems that class components are on the way | out, and are around mostly due to backwards compatibility. But it | is true that a lot of legacy code uses them. I wish they'd have | started with functional components, but I can't blame the team | for not figuring out all of the details in advance. | | I'm curious what others think. Thanks! | RedBeetDeadpool wrote: | Is `more stuff to learn` seriously a critique? I mean if you want | to stop learning stuff then maybe, go live in your own little | bubble. | | The other criticisms seem a little bit like someone who doesn't | understand how hooks works criticizing how hooks work because he | doesn't understand how hooks work. Perhaps, he doesn't understand | how hooks work because he doesn't want to learn more stuff? | jtdev wrote: | The universe is stateful; no matter how hard FP zealots try to | abstract that out of code, they will never change this | fundamental fact. | tome wrote: | The universe is also highly concurrent and probabilistic, but | that doesn't mean we need to design our programming languages | that way. | nightski wrote: | FP does not do that. | | First of all, there is stateful code and then there is | effectful code. It sounds like you are talking about the | second, not the first. You can have tons of state and remain | mathematically pure. | | Where people get hung up is effectful code, or mutable state. | Even one of the more hardcore FP languages, Haskell, does not | try to abstract that out. Instead it embraces it fully by | giving constructs in the language to describe and control | effects! This is far more powerful than straight up imperative | languages. If anything, writing mutable, effectful code is more | powerful in Haskell than in C/C++. | | Where Haskell gets difficult is when writing effectful code | that interacts with external C libraries and the OS. But this | has nothing to do with purity, state, or effects. It really | only has to do with the fact that it is designed to have lazy | evaluation by default. Which itself has a lot of advantages, | but it makes this interaction more difficult as code does not | execute in the same order as you write it. | | You may find that languages such as OCaml, which are fully | functional and have strict evaluation are a joy to work with. | TheCoelacanth wrote: | Nonsense. These are all just techniques for modeling reality, | not reality itself. | | You could model the universe just as accurately as a stateless | function of time as you could as a stateful entity that moves | through time. | desc wrote: | I'm going to express something a lot of people are thinking and | are being far too diplomatic about. | | React Hooks are a _fucking stupid idea_ and always were. | | They're basically just adding dynamic scoping to a language and | framework which doesn't need it, in one of the most 'magical' and | confusing ways possible. You have to care about execution order | to understand exactly how they'll all work and that _will_ bite | you eventually if you 're building anything without knowledge of | all the contexts in which it's called. | | There's a reason that most languages stick to lexical scoping: | you can _see_ the dependencies, in the same file. | | And a large portion of the value of functional languages is that | they avoid state, making magic-at-a-distance impossible. | | Boilerplate is not the problem. Magic is the problem. | jonny_eh wrote: | I never understood what was wrong with class components | anyways. What did Hooks bring that couldn't be done in an | easier to understand way with class components? | Gehinnn wrote: | Yes. Except mobx ;) I like to use function components together | with class based observable view models. Only a single hook | wires them up. Works like a charm and avoids all the IMHO | confusing hook complexity. | desc wrote: | Hmm, so the reusable bit is the straightforward inject- | everything component, driven by an app-specific, app-aware | hook-using part? | | I can see how that can work for simple cases. Nesting | components is going to get tricky though if the classes don't | operate exactly the way the hooks expect. | | Of course that's the problem: someone built hooks for their | trivial cases and now they're the 'preferred' approach... | pattrn wrote: | It's a unfortunate that he doesn't include the equivalent class- | based implementations of his logging quiz. Event lifecycles | notoriously obscure order of execution, so I'm not sure the | alternative is any clearer -- especially not with contrived | examples. In my experience with both hooks and classes: | | - Hooks require substantially less boilerplate than classes. | | - Rendering optimization problems with hooks tend to take more | time to identify and to fix. | | There are other pros/cons, but these are the ones that affect my | work most frequently. | mstudio wrote: | I have some similar gripes. I find Hooks to save a bit of coding | overall. I've found my functional components to be about 10-20% | smaller than my class components. I'm not 100% convinced it's | really worth it, though. | | With class components, my state/props are clearly defined within | the constructor and/or PropTypes. This makes it easy to | understand the overall architecture of a component. Functional | components with Hooks don't have the same sort of structure and | can be difficult to understand at a glance. | | One of my gripes with Hooks is that listening for async state | updates requires more code/complexity than w/classes. In a | traditional class component, you can add a second, optional | argument as a callback which is called when the state has | updated: setState({ myState: 'newValue' }, () => | { this.doSomething(); }); | | With Hooks, that doesn't apply. The useState "set" function | doesn't have a similar argument. | setMyState('newState'); | | Instead, you need to use 'useEffect' with an optional argument: | useEffect(() => { doSomething(); }, [myState]); | | This leads to potentially having many "useEffects" scattered | throughout the component. | | That said, this is just my experience with Hooks after a few | months of working with them. It's entirely possible that I just | haven't had enough experience with them yet. | city41 wrote: | Components with lots of hooks in them remind me of | spreadsheets. I find myself tracing from one hook dependency | array to the next, trying to follow the logic. | eat_veggies wrote: | Having a separate useEffect certainly scatters your code, but | it helps prevents bugs that cause your states/effects to go out | of sync. | | If you use a callback on setState in order to listen for async | state updates like setState({ myState: | 'newValue' }, () => { this.doSomething(); }); | | then a week later, when you add some different code calling | setState({ myState: 'newValue' }) somewhere else without | remembering to add the callback, your callback won't run! | Callbacks kind of break the declarative/reactive model. | zodiac wrote: | I personally don't use hooks (or functional components) at all, | but recently read this post from Dan Abramov about algebraic | effects which makes a point (among others) the hook mechanism is | a pretty simple way to implement state/effects/context in a | language with algebraic effects. | | https://overreacted.io/algebraic-effects-for-the-rest-of-us/ | jtdev wrote: | Yay, just what we all needed to help us write clean, | maintainable code... algebraic effects?? | zodiac wrote: | Honestly? Maybe it is, maybe it isn't. Imagine replacing | "algebraic effects" in your question with "exceptions" - | theres no clear answer. What do you think? | sebringj wrote: | My take away from hooks is that it is pushing toward making your | components simpler. One of the gotchas of hooks is that it kind | of "lies" in the way it looks. Take useRef or useState for | example. These things are only defined one time even though the | are declared in such a way to look like they are defined over and | over again each render. They are actually key lookups under the | hood. This was a main point of confusion for me initially and I'm | sure I'll find out more that I assumed incorrectly as I go. Auto- | magic sometimes is confusing to me. | karatestomp wrote: | They behave like class property & method declarations. But | scattered about in a function and looked up by order rather | than name. This is exciting and not considered redundant and | obviously a bad idea, for some reason. | Saaster wrote: | My biggest worry with React is that it has restless developers | with idle hands. | | I have (a lot of) component code that will never be converted to | hooks. Can I rely on you not to flake out and pull an Angular on | me? | karatestomp wrote: | > My biggest worry with React is that it has restless | developers with idle hands. | | That's exactly what I take hooks as a sign of. I read the | papers and the code when they came out. I still don't get why | they exist except to provide churn to work on. A half- | reimplementation of objects with a super weird syntax in a | language that already has objects seems like misguided make- | work on a project that's already basically "done" except for | the boring, non-flashy work of maintenance and subtler | improvements. | city41 wrote: | Overall I think hooks are a fine addition to the React toolbox. | But I think they are very easy to overuse and the complexity of | hooks seems to increase exponentially. I've been involved in two | code bases now where hooks are just everywhere and they were both | an absolute nightmare. But I've also been involved in code bases | where hooks are used more sparingly, about on par with when HoCs | were used, and it's rather pleasant. In general, the more "dumb" | components your app has, the more manageable it seems to be | overall. ___________________________________________________________________ (page generated 2020-04-27 23:00 UTC)