2021-04-26
2564
#react
Paul Cowan
5524
Apr 26, 2021 â‹… 9 min read

Understanding common frustrations with React Hooks

Paul Cowan Contract software developer.

Recent posts:

Rust logo over black marble background.

Handling memory leaks in Rust

Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.

Ukeje Goodness
Nov 20, 2024 â‹… 4 min read
Robot pretending to be a person.

Using curl-impersonate in Node.js to avoid blocks

Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.

Antonello Zanini
Nov 20, 2024 â‹… 13 min read
Solving Eventual Consistency In Frontend

Solving eventual consistency in frontend

Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.

Kayode Adeniyi
Nov 19, 2024 â‹… 6 min read
How To Use Lazy Initialization Pattern With Rust 1.80

How to use the lazy initialization pattern with Rust 1.80

Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.

Yashodhan Joshi
Nov 18, 2024 â‹… 5 min read
View all posts

90 Replies to "Understanding common frustrations with React Hooks"

  1. Exactly! They are admitting a design mistake and the fix is…. to create an entirely new paradigm?? Come on now.

    And the idea that code is duplicated between lifecycle methods has to be the flimsiest of excuses possible. Who are these people complaining about this? People that don’t know how to refactor code into a shared function? People that walk into doors because they forgot they had to open them first?

    Hooks seem like an odd form of bandwagoning to me. OOP is passe, and FP is the new hotness. But hooks now introduce state into functions. These are no longer the functions of FP. They are not referentially transparent pure functions. They are merely the procedures or subroutines of, say, Visual Basic, with some weird state mechanism grafted on. Side-effects everywhere!

    But you know what’s really great for state and side-effects? You know what paradigm we’ve had since the 1980s and earlier for this? OBJECTS AND CLASSES!

  2. Wow.. I didn’t realize there were others not happy with Hooks. I haven’t jumped on the Hooks bandwagon yet, hopefully i can hold off for a bit longer. I am happy to keep writing Class components as they are easy to read and understand; Readability and clarity are more important to me than some fancy new hotness; just the hooks syntax in itself is confusing the crap out of me, let alone all the gotchas that I will encounter later when I finally use hooks. Hopefully the gurus in the React team don’t find an excuse to remove Class components in React v17 !

  3. Hopefully more people do the same. I think a lot of people are scared to admit they don’t like hooks. Classes are more verbose, in a good way.

  4. Hooks sintax looks clean but there are many issues when we try to imitate lifecycles,so,i hope in next releases react team will solve better this dependency array,for now,hooks only do well job with CDM && CDU.

  5. I feel your pain as an oldtimer who has travelled widely in dev circles for over 20 years. Having spent time in Erlang and Haskell, I thought React Hooks would be the reason to get excited about React.

    However, it took me almost 30 minutes of experimentation and digging through the docs, blog posts, etc to finally understand why this didn’t trigger a re-render:
    “`
    const [flavors, setFlavorSelection] = useState(initFlavorsObj)
    setFlavorSelection( Object.assign( …flavorSelection, {[key]: (flavorSelection[key] += 1)}))
    “`
    This is the answer ( shallow comparison but I should have thought about that first! )
    “`
    setFlavorSelection( Object.assign({}, …flavorSelection, {[key]: (flavorSelection[key] += 1)}))
    “`
    I’m also starting to see folks use Hooks where better functional concepts such as curries, composition, etc are better suited. I also see custom hooks which are an awful amalgamation of noodle code. Devs who devote 80 hours to learning hooks would be better off learning something else. Let’s face it, React is really showing it’s age and Hooks do not get React closer to functional programming paradigms/frameworks like Elm or Reason

  6. After trying to use function components and hooks in a real-world project several times, I always returned to class components. Unless your function components are incredibly simple things can get very messy and complex very quickly. I do like the idea of function components and hooks, but I certainly don’t enjoy working with them in their current form.

    The React team’s reasoning for the introduction of hooks is also sketchy. Reusing code? Surely that comes as part of sensible design decisions, e.g. DRY. Not understanding how this.* works? That’s something that doesn’t just affect class instances, it affects JS as a whole; if you don’t understand it then your career as a JS/TS programmer will be going nowhere fast.

    The code base for a typical project also contains a lot more than components. Having one part of the code using one paradigm (function components), and another part of the code using a different paradigm (oop), is disconcerting at best.

    I don’t believe the React team will deprecate class components for a long time, and when they do I will be taking a cut of their source code to preserve class components, but when the team do eventually deprecate class components I imagine that will be the beginning of the end for React as we know it. Vue may become the de-facto standard at that point unless something new and magical arrives in the meantime.

    A new/separate React Component 2.0 would have been a better solution, in my opinion.

    1. Deprecating componentWillReceiveProps and substituting it with the static getDerivedStateFromProps is big step towards deprecating class components.

  7. Recently I was trying to use hooks in my project, ended giving up. It’s too painful to use, like writing multiple useEffect? I know it’s a ‘separate concern’ thing, but kinda verbose to me. Let alone the dependency array, messing up the lifescycle finally made me giving up, I’m sticking with class component for now.

  8. Hey Chris, I totally appreciate your frustrations because it reminds me of myself last July/August/September when I was getting up to speed with React Hooks. In contrast though, last week I had to delve into a colleague’s older class component React code and I found it painful. I suppose I’ve gotten so used to doing things “the new way” that it’s now painful to go back.

    Whenever I’m tasked with teaching someone React Hooks, I always encourage them to think about doing things “indirectly” rather than “directly”. So, for example, say we had an app where the user entered a UPC code off of a barcode and then pressed Submit to look up that product’s info.

    In my app I would wire up the `onChange` event of the Input element to a `useState` variable like this:

    “`
    const [ upc, setUpc ] = useState(null);

    setUpc(event.target.value)} />
    “`

    And then the Submit button would be wired up along with a `useState` variable like this:

    “`
    const [ isGetProductInfo, setIsGetProductInfo ] = useState(false);
    setIsGetProductInfo(true)}>Submit
    “`

    Then there would be a `useEffect` like this to fetch and save the product’s info:

    “`
    const [ productInfo, setProductInfo ] = useState(null);
    useEffect(() => {
    if (isGetProductInfo) {
    requests.get(`$(requests.API_ROOT())account_services/product_lookup/$(upc)`)
    .then(response => {
    setProductInfo(response.data);
    }
    .catch(error => { … }
    );
    setIsGetProductInfo(false);
    }
    }, [isGetProductInfo]);
    “`

    I realize this code is very basic but it illustrates a successful pattern of code to demonstrate using functional components, `useEffect`, and `useState` in React. Hope it helps!

  9. IMHO hooks are a poor implementation of functional reactive programming (FRP)… But it is a welcome first step into that direction. At least it provides local behaviors, so no need to read all component code to understand what is going on.

    Even better would be a real synchronous dataflow programming language for UIs, something like Lucid Synchrone did for DSPs. Unfortunately, earlier attempts like FlapJAX didn’t catch on, neither do new great libraries like SodiumFRP. RxJS seems to catch on, but is asynchronous, and not very suitable for UI programming due to its glitches. Maybe Svelte will do better. MobX already works for many people, but is limited compared to real FRP.

    Again IMO when you look at user interfaces as a circuit of signals, many hard programming problems become easier, and more scalable. You actually don’t need a virtual DOM either for this, Functional Reactive Programming is about taming mutable state, not avoiding it. You just connect the mutable cells of data, and let the runtime sort the dataflow graph according to ranks, and you get perfectly deterministic, testable and reason-able behavior.

    Too bad no popular frameworks takes such an approach, most likely because most of us are either imperative programmers, object oriented programmers, or functional programmers. Functional Reactive Programming is really different, it is actually dataflow programming, something that is very popular in spreadsheets, 3D software (Maya, Houdini, Substance Designer), and Digital Signal Processing. But not yet in the frontend world.

  10. I absolutely love hooks. They make state management so much easier to understand and read. I can understand frustration as it is a different way to think especially when coming from classes. But there is so much more flexibility with using hooks and they do offer performance enhancements. They open up a pandoras box of possibilities especially in the global state management realm. There is always pain when learning new things but do not get stuck in the older ways. Hooks are the future and I am excited to see them mature.

  11. Very good article…
    I have also noticed the repition of code in Lifecycle blocks of React. That was a point of concern, sometime you would have to repeat code in componentWillRecieveProps also. That was a bit furstrating.

  12. Wouldn’t it be easier just to make the useFetch depend on “skip”? Then in the click handler you could just update skip and React would handle refetching the data.

  13. Well put. A paradigm shift require a different way of thinking. The frustration and struggle coming from this article stems from trying to shoehorn hooks into the old way of thinking.

  14. I thought the same for a while, but now it’s clear to me this is fallacious. Yes, there is frustration as well but for beginners as they make the shift; After building a significant feature, I have been starting to hit these issued discussed by OP and I have scratched my head aplenty, this complexity cannot be blamed on incapability of the community at large in adaptation. A lot of people are even jumpshipping as the foresee the direction we are going, luckily for my main Product, I started out with Vue and it’s staying that way.

    These issues certainly need to be incrementally addressed within minor version(s) rather than leaving progress to radical changes like Facebook has been doing. I am skeptical at this point, perhaps they like shocking the community to keep themselves relevant, and then leave half-assed documentation to promote discussions, courses and discourse around react in general.

  15. ^THIS

    Hooks are really frustrating, it’s a step in the right direction, but 10 steps back in everything else!

    I’ve been using xState and react, mostly with an HoC pattern and it’s been working beautifully. xState is a FSM library that allows independent state machines to communicate via events/messages. I’ve adopted an approach similar to Erlang/Elixir and it has worked wonders in the frontend world.
    Components are simple functions: props in, html out. Every action send a signal/event and actors react to it, sometimes communicating with other actors, other times just triggering re renders. You get this nice conceptual graph that you can visualise and see how an action interacts with your whole app.
    Adding new functionality is usually a case of simply spent routing events to the appropriate actors, with the occasional new actor when a new behaviour is required.

  16. “and there is no way to override this functionality and supply a custom comparator.”

    what would you like to use as a comparator?

    you want to compare for example user.id it’s easy just give user.id in the dependency array instead of user…user wouldn’t make sense:

    const x = {name: “john”, age: 30};
    const y = {name: “john”, age: 30};

    console.log(x === y); // false
    console.log(Object.is(x, y)); // false

  17. Sry but I think you didn’t get hooks correctly. Hooks have states, but the state in a hook is immutable, it doesn’t change!

    Everytime you say setState(newState) in a hook, you tell React: call this function with the new value for this state (you can think of it more like function arguments).

    Unlike in Class-Components, this.state is mutable which means it changes in TIME which means side-effects!

  18. React will be eventually ruined by its hooks.
    You can see that the fundamental concept of React is to organize the HTML components into classes / objects.

    Hooks are like noobs in programming to put everything in the Global scope because they are lazy to know what is static functions, what is JS class object, how classes should be constructed, how the components should be organized, lazy to know about the mechanism in such frameworks but just do not want any restrictions in their coding to achieve their one-off results.

    I can seldom find normal piece of JS works that is properly organized.
    I am afraid that this profession has been a great volume of water inside nowadays.

    I just want to say, JS has a reason to move from class-less to class.

  19. I agree with the author that mostly I like hooks but there is hidden complexity. Maybe the complexity is just in plain site with classes but it does pose the same issues. The issue mainly are developers and their ideas on how things work based on their current understanding. With hooks it’s all too easy to place them with the component you are rendering this causes a coupling of the data to the presentation. I’ve hardly seen any code that passes the data retrieved into a pure component with no concerns with data. Hooks doesn’t lend to such a coding style as it’s not convenient to separate the “connected” component to the “non-connected” components.

    Tools will always change and have disadvantages and advantages. I hope this is a stepping stone to a better React in the future and it won’t ruin React because the grass isn’t always greener on the other side.

  20. In reality most of the complaints I see here in the comments are just people not actually using them the right way.

  21. My only true complaint around hooks is that there are too many libraries that have bandwaggoned into *only* supporting hooks, so that I’m *required* to wrap my more complex class component (because there is definitely still a strong need for both) in a functional component, just so I can pass the hook result into the class component as a prop

  22. When i first learnt ReactJS, i loved it the way class based component works and the easiest to understand. suddenly the hooks took away the limelight and forced us to learn react from scratch and shift it. now at this point of development I regret; why the hack was hooks needed? and if needed then why to put so much on it to replace the classes.. class method was a standard way of doing and i pray React gods to rethink.. Classes are more elegant way of doing things. Hooks are confusing not only developers but the end product. Better waste your time to improve the class based methods. Otherwise you won’t stand in competition for log run as hooks are not the way developers would like to approach.

    My vote for Classes.

  23. There’s a fundamental issue with using implementations like `useFetch` hook. Even though this is presented like feature of hooks.

    For ex. you have simple TODO app. You get the list using `useFetch`. Everything is good so far. The problem arises when you save a new item. If you got the list using the `useFetch` hook, you will be unable to refresh the data, without using workarounds, which defeats the purpose of using that kind of hook in the first place.

    1. Hooks can (and often should) be used inside other hooks. In your case, you should probably create a useTodoList hook, complete with data fetching (using useFetch) and state management. Then, from the useTodoList hook, you simply return the todoList state, along with functions to create/add/update data.

      1. Yes, this is the way it is typically done and I’m yet to find a better way but imho such hooks have too many responsibilities, fetching, updating and maintaining state. It’s a lot of pack into one function and yet I often see people doing this because this is the path of least resistance when working with hooks. The alternative is to have separate hooks (one for fetching and one for updating) but then you have to manage sharing state between them.

  24. Hooks seem to me to be the poster child of a leaky and bad abstraction. They look nice in simple examples, but as soon as you try to do anything with real world complexity, then you quickly end up going down a rabbit hole of dependency trees, deep properties, stale encapsulations and the like.

    For example, to create an interval or timeout callback function which examines or changes the component state you have to consider that the state variable that existed at the time the callback function was created might be a stale version of the state, so you have to make sure that you clearInterval or clearTimeout to unregister the old callback and then recreate it with something that points at the newest version of the state variable or you have to use other techniques involving “useRef” or “useCallback”.

    You end up having to spend a great deal of mental energy reasoning about how the hooks system works under the hood in order to use in all but the most basic and contrived cases. I can’t really fathom why the powers that be at Facebook thought that it would good to abstract state using immutable variables that are recreated each render, but then create a bunch of backdoors and workarounds rather than just have a simple mutable this.state. I suppose that it was probably a case of the React team needing to justify their own existence by releasing new and revolutionary features rather than just making incremental improvements.

  25. I want to lay some points from my perspective as a dev who wrote big project with both classes and hooks.

    1. useEffect

    Pros:
    – separating concerns

    – adding clarity when something should be reactive (always use useEffect dependancy array linted)

    – adding clarity where is the “logic” in the component

    – tip: keep useEffects as small as possible. For bigger ones you can replace arrow function with normal one to use the name to describe the effect: useEffect(function thisIsProductDecision() { }, []);

    – helps you to handle easily clean ups (timers, CRUD etc).

    Cons:
    – can get hard to understand if the dependancy array gets big. This is why you should strive to separate as much as possible.

    2. useState
    Pros:

    – possibility to update a single state instance and not the entire component state

    Cons:
    – makes it a bit hard if you decide to work with one object state insteaed of separated onces

    3. Class components

    I read people saying class components are easier to read and understand. I can’t agree with this statement not only because I beleive it’s just a habit but because class components:

    – Have more complex structure. You can write code which jumps trough time and space like Rick and Morty: didMount, willMount, willReceiveProps, didUpdate etc. All of those are too specific time events which can interfier with one another and puzzle the reader and the writer. I feel that useEffects and hook based React is more one diirectional and it makes you think not in “time” and “when” something will happen but in more reactive way as “why” something happened (state changed in dependancy array). Instead of mastering and deeply understand 10 lifecycle events, and understand how they can interact/interfere with eachother, with hooks you need to do that only once for only one thing: useEffect. If you master that, you mastered React.

    – Sharing business logic you must agree is not easy, readable and the solutions like HOC are running away of the declarative nature to which we should strive. Custom hooks are more prediictable, strict and easy to understand then 5 nested HOCs.

    – Classes gives the OOP feel into React, which React is not trying to do. This happened very clear with the Hook based React, where the functional path is layed in it’s roots. There is nothing wrong with OOP (probably) but if this is what you want, go to Angular.

    In the end you can create good, readable and scalable project with both classes and hooks and you can also do the opposite with both of them. React is a tool and the people working with it are responsible of the outcome. Eeither way I think that Hooks based React is a more elegant, functional and advanced tool.

    By the way I’ll appreciate if you give a go with my state manager package which is (I think) more powerfull then Redux and much much easier to use: https://www.npmjs.com/package/store-me

  26. React hooks are a problem. Instead of micro updating state, you’re left with doing giant monolithic updates of ALL of the state. You can’t simply just setSomeState, then setMoreState in sequence. This causes components to unmount and things just break. The paradigm now is “gigantic global state updates everywhere”. How is this not a problem?

  27. Ever try updating state within a recursive setTimeout function? Dan keeps on doubling down saying that React + hooks aren’t broken but it’s pretty obvious now that he just won’t admit he’s wrong (and he is).

  28. I dislike hooks because my colleagues abuse them. They go too far with using them when a different approach would be better (objectively!).
    And the article does not even talk about testing. Wow, how did this get so bad so quickly? Also, unnecessarily coupling business logic with the view layer makes it so much harder to refactor. I understand that in some cases the solution with hooks will be more elegant, but overall seeing what is happening in a large code base on which I am working on, I think it’s a step back from code evolution standpoint.

Leave a Reply