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