As you've been using/learning about React Hooks, what have been the hardest parts for you? #discuss
For further actions, you may consider blocking this person and/or reporting abuse
As you've been using/learning about React Hooks, what have been the hardest parts for you? #discuss
For further actions, you may consider blocking this person and/or reporting abuse
Dima Vyshniakov -
Agbo, Daniel Onuoha -
Dan Calderon -
Fupeng Wang -
Top comments (66)
They work like black magic.
It's actually kind of clear why they behave like they do (they're called in sequence), but the consequences in terms of code organization and structure are... meaningful, at least, if not outright jarring.
You can't have a hook called inside an
if
branch, for start. That's enough to be a game changer. But then, the usual lifecycle hooks likecomponentDidMount
and so on are all condensed insideuseEffect
with its special second argument logic.With classes we had a clear idea of the lifecycle of a component. With hooks it's distributed inside a lot of
use*
functions with often not really meaningful names.Not that the names chosen by the React team are clear either, mind you.
useCallback
,useReducer
,useLayoutEffect
and so on aren't IMO clear at all about their intent and usage. Compare those names with the aforementionedcomponentDidMount
.I've found myself read the documentation about them more times than I'd have liked to. And I think I'll do that again on the next project 😔
All in all, I think hooks are a clever and simple solution to most of the reactive application problems, but they're a shifting paradigm - not that it's unsurmountable but enough to make "classic" React something completely alien. At this point, would it be so bad to fork React into a hooks-only separate library?
I agree with this, but I feel that its way too late now. Also is the intention to eventually fade out "classic" react?
Interesting statement. Hooks became stable on Fabruary 6th with React 16.8, not even 6 months ago. When do you think it was the appropriate time? Maybe before so many libraries using hooks popped out like mushrooms after the rain? 😅
They (React maintainers) said there's no intention to dismiss class components in the foreseeable future. But what about the hidden intentions? In the end, the explicit goal was to push developers away from class components.
Was release only ~6 months ago? I started playing with hooks before full release though, so feels longer to me I guess...
I feel like the right time should have been when I was announced and was known to be so dramatically different. Have it as a React add-on. I imagine that there would be way less usage of it if that was the case though.
Idk really, maybe the ideal solution would be to go the babel route?
@React/core
with optional@React/classes
and@React/hooks
or something.I expect that classes will eventually be extracted to a separate package and a codemod will be made available to update code to use that package, similar to what was done with
React.createClass
. The react team is very interested in making it easier to build UIs with React and they feel that hooks is the way to do this. So putting hooks in a separate package wouldn't have pushed their goals forward very well. I'm happy with the way it's been done so far. It's a change, and that comes with a learning curve, but it's one that I'm glad to have for the benefits that hooks provide.That's an interesting insight, Kent. Thank you!
Consider watching youtube.com/watch?v=KJP1E-Y-xyo
If I have to consider something, give me a hint of what it's about 😄
Anyway, interesting video, very clear. Shawn is excellent at explaining stuff.
But, IMO, the point still remain. A developer could learn those things, but they shouldn't be forced to do so. They're glimpses of the internals of hooks. But, as Shawn says at the end of the video, that's not React - so it's unclear how, for example, removing a component from the tree affects the hooks array. Or why you can't use hooks inside class components. Or why there's a
useEffect
hook but also auseLayoutEffect
and how - or why! - they differ.This is complicated by the fact that function components do have a lifecycle just like class components, but it's hidden under the rug of hooks.
I personally think it’s only complicated because we’re so steeped in OOP and lifecycle methods this seems so alien.
Yes, that indeed might be the case.
I also wonder why, at this point, it is the case. I.e., why a lifecycle seems so natural at this point. It's not like someone imposed this concept on everyone - maybe it's just because we usually see something "coming to life", "living" and "dying" that we apply this idea even to application components 😬
Also, React indeed has a "cycle" to make things work - the work loop. Which works well with JavaScript's event loop too.
In the end, I'm unsure if there are solid, evident advantages about hooks that makes us say that they're definitely the better way to create (React) components. They comes with compromises, like basically everything else, and I'm unconvinced that the drawbacks could be nullified by mere habit.
But for now, I still think it's too soon to declare something.
My feeling at the moment is that Hooks is an attempt to solve issues they created themselves by pushing functional programming too far (HOC wrapper hell, etc.).
That's weird because it's pretty easy and elegant to avoid those problems if you use the right OOP patterns (adapters, dependency injection...).
I wish they had improved the class usage rather than introducing those terrible, anti-pattern, useThings.
They are shiny and new, they are nice for small components and todo demo apps, but for large apps, the problems remain.
That's an interesting take as they're using closures. Which as you may know isn't new, nor specifically "functional".
HOC wrapper hell is also interesting as in my experience most HOCs issues are down to bad architecture and exhibit similar as inheritance.
"They are shiny and new" - they're old. Only new in React land.
To add to this already great comment, hooks have felt more like a fad, not only in the way it was introduced but also the way it was adopted. For example, hooks was released partly to help with newer developers that don't understand classes. Some of my primary concerns are that the JavaScript community and ES standards have been heading in the direction of more OOP with ES6 -> ESNext. Hooks are a fork essentially moving away from that and more down the functional route. I agree there are times and places for hooks, but I feel they can be overused.
For instance, when you come across a functional component that has 6 different useEffect calls, the function ends up being 1k lines long, which isn't manageable. The same goes for finding a class componentWillReceiveProps that is super long too, the tool is only as good as the person using it.
My disappointment with hooks lead me to write a small HOC that allows writing stateful components without functions, and with all the functionalities of classes.
github.com/Pensarfeo/react-makesta...
This is highly experimental, so I would appreciate some feedback on the project!
PS: No hooks were harm wile writing this package :)
One of the most common struggles I've seen people have is not being able to remove the idea of imperative life cycles from their mental flow, and switching to thinking in terms of declarative effects.
It's really strongly ingrained in a lot of users to think more about mounting, updating, and unmounting instead of just rendering, and what (effect) you want to happen when you render, given some state.
I find this is the most unnatural part of hooks: the lifecycle paradigm fit the mental model of React/DOM interaction a lot better than hooks, and many integrations with non-React libraries require instantiating on mount and destroying on unmount.
This is very true
It's been a common riff the last few days, so I've written a post on it: dev.to/samsch_org/effects-are-not-...
useState(false)
😱,useEffect()
🤔). It's not meaningful, and this is not a good sign. I've worked with many languages and I've never seen anything like that. We're not all React pundits / teachers. Many of us are fullstack devs having to deal with other languages, Kubernetes, etc and deliver real work, and with Hooks, more "Javascript fatigue" ensues.I would love to know why the React team hates classes so much. It's a similar story with Vue, they're pushing anti-classes rhetoric when there is nothing wrong with classes. The arguments people have against them all mostly relate to inheritance, completing ignorant of the fact this is the reason we have decorators (for metaprogramming).
Angular and Aurelia devs have been building apps just fine with classes since 2015. It seems to me that React and now Vue is so against them because their designs predate ES classes and classes are a convenient scapegoat for outdated architecture. I have never seen a valid argument against classes in Javascript that didn't boil down to personal opinion or design differences.
Your comment deserves more upvotes.
It's just one day old :-)
References in custom hooks
For me, one the hardest thing with hooks is about following the references when creating custom hooks.
I end up with a lot of
useMemo()
s and the "not recommended" useEventCallback technique and a lot of ref tracing of make sure it's not my custom hook causing unnecessary renders.Example:
Async effect without use actions
Also, any async effects that change state but are not caused by a user action, such as loading a list of things when first rendering a component...
...makes the component annoying to test because it currently throws up a warning about not being wrapped in act and currently
act()
is a synchronous callThere is going to be a "fix in the next version", about the asynchronous part, but will it help with async effects that have no user action to initiate them?
Reset state based on props
Also I often find myself wishing I could "reset the state" based on a prop change. The only easy work around I've found that seems to work is just dispatching/calling a callback in
useEffect
that run when the prop changes.If you want to reset all the state, you can assign that prop the key of the component, and it will rebuild that component in it's original state
Right, yes thank you, I can push the problem up and reset with a key.
But you know, sometimes it’s not the only state, and it would be nice to solve the problem internally in the component rather than lift the problem up, but yes, great idea, thanks
Hmmm, interesting. My brain's not going to let this one go... Could you provide a concrete example? and I'll let you know what I come up with.
Okay @wolverineks , here's a derived but concrete example:
Let's say you've got a component that lists the members of a team, and you can switch the teams and view the different members in the members-list.
In that list, each team member has a small UI state, to determine if the details view is showing, this doesn't seem appropriate to add to the team-member itself, because that object is provided from elsewhere (global/domain state), and it is really just a UI concern.
In the list of members, there is also a toggle with the option to "Hide Inactive Members", so you may not want to use the "reset with a key" method when the team changes, because you'd lose the "Hide Inactive Members" state.
So in the example above, you can look at the custom hook
use-open-state.js
and see that what I am doing is usinguseEffect
to re-set the state for "what's open" whenever the list changes.There are lot's of ways to solve this particular problem, keep a member mapping in state no matter what team shows, some crazy memoization, moving the "hide inactive members" state out of the members list (and use
key
to reset instead)... lot's of ways, it's not an insurmountable problem.But my point was, I often find myself wishing
useState()
(oruseReducer()
) would take an inputs/deps argument likeuseEffect/useMemo/useCallback
, so I could just reset my initial state based on a prop.Something like...
I think that would be swell.
I think the simplest solution to this problem is to Lift State Up no?
Well, personally I think
useState()
having a method of reseting state would be the 'simplest' solution......but yes, I could lift the state out of the
MembersList
, and convert it to a fully controlled stateless component, and just reset the state in the handler for theTeam
's dropdownonChange
. Definitely another good way to solve the problem.I guess maybe I am the only one who ever felt like they wanted a way to reset the state in
useState()
oruseReducer()
I guess this post is kinda old - but it popped up today in my Dev.to feed, so...
On a practical level, I've noticed that the "life cycle" of Hooks isn't completely analogous to class-based components. This has caused me some degree of headaches, and I've only recently begun using Hooks heavily. They say things in the docs like "this Hook is analogous to this lifecycle method", but, umm... not exactly. I know that part of this is just about learning the ins-and-outs of Hooks, but it can still be frustrating when you've pretty-much mastered class-based components.
On a more subjective level, I have a really hard time whenever I'm doing "Pattern X" and then someone comes along (like Dan Abramov) and says, "Yeah... that other way you're doing everything sucks - so you should do it instead with 'Pattern Y'." To be clear, I'm always open to reading/hearing about new innovations. But when I see the "innovation", I need to see some compelling reason to switch. And no, the reason can't simply be, "The Old Method is stooopid and the New Method is awesome - so use the new method." That kinda "reasoning" is a quick way to turn me off to the new concept.
I've now done a fair amount of work converting class-based components to function-based components with Hooks. For the vast majority of these "refurbished" components, when I'm done with the conversion, I sit back and look at the difference and think, "Yeah... it's basically the same thing, with just a modestly-different syntax." And by now, there are many blogs/tutorials/etc that purport to show you how your old, stodgy class-based components can be converted to Hooks. Inevitably, the author drones on about how much "better" the Hooks version is. They declare it to be "cleaner". And yet... it looks damn-near the same.
But like so many of the other elitist trends in the JavaScript community, once the fanboys decide that Pattern Y is just clearly superior to Pattern X, there's no reasoning with them. To be honest, I've kinda given up the theoretical fight, because I'm tired of someone (e.g., hiring managers) looking down their noses at my horrible, ugly, unconscionable code that uses class-based components. If I showed a lot of React devs how I've managed to delivered quantum computing in JavaScript - but I did it in (egads!) a class-based component, there are just too many fanboys out there who will scrunch up their face and look at my revolutionary code as though it's the digital equivalent of a fart.
FWIW, I wrote an entire post about the odd demonization of the
class
keyword in JavaScript:dev.to/bytebodger/the-class-boogey...
Another thing that I don't particularly like about Hooks is that they feel very much like an all-or-nothing proposition. Yes, I know that you can use functional, Hook-based components in the same codebase with old-fashioned class-based components, but I've already seen that run into a series of headaches that I would've never had to deal with if the Hooks Cartel hadn't decided that "Classes are bad... mmmkay???"
The part that got me (reminded me of because of this comment) that hooks don't share "states", but it's for sharing "logics".
Another one being
useEffect
. I still refer back to A Complte Guide to useEffect often.useEffect
still has clicked 100% especially on parts with getting new fresh value (usingref
).Shifting the way I think about components, from lifecycles to instances, especially when converting large components that rely on those lifecycles.
The end result is always clearer and easier to read code. Getting there requires some thought.
Could you clarify what you mean by "instances?"
What I mean is, rather than thinking “should this component update?” I instead can shift my thinking to “my props have changed, how should this instance of my component react to them?”
I hate how
useEffect
works.I'd prefer having lifecycle back.
My main reason?
Is a hook that has many concerns. I prefer to think of functions as things that does only one thing right and nothing else.
I've tried a PoC for the project I'm working on and useEffect had very tricky behaviors at first.
Just think a bit about it:
If you want to do something on every render:
If you want to trigger something based on change of only one variable:
If you want to trigger on mount:
If you want to trigger something on unmount:
And what about cleanup functions?
Do you think they behave the same on all the cases?
Oh, my dear friend let me tell you that you're totally wrong.
As I said before, this works on component unmount:
And being honest I don't know when/why is the cleanup function is called here:
That's my two cents about it.
I've been able to keep state closer to the component but I'm not sure if that's a great paradigm? Not sure. Maybe I am using hooks incorrectly, but I am making smaller api calls in the component than at a HOC and being able to reuse that data like when using redux. Is that good? Also, having trouble figuring out using hooks to its highest ability. Right now, it's nice to
useState
instead of having to care about this.state or this.setState orthis
in general but how to design components truly reusable. I saw a good example with an infinteScroll example hook but thinking about it on my own is difficult.There are also no best practices (I think) so refactoring class components to functional, I don't know the benefits aside of it being more modular
I like using hooks. I don't like too much using classes. I have learned React from the beginning using hooks, not classes. The most interesting thing about
useEffect
is how it can pass from two renders to infinite loop changing only a little bit the second dependency parameter. Or for example, if you useuseReducer
anddispatch
an action, you must know that the effect of thisdispatch
will not be visible until the next render, so you have to put your code insideuseEffect
in order to take account for thisdispatch
. So you end up using a lot ofuseEffect
. Sometimes it's difficult to tune the second argument foruseEffect
. As a project I made myself the minesweeper game using hooks. It was cool to do that and I learned quite a lot. Or sometimes doing little test projects with a lot ofconsole.log
s to see what is going on with renders. With time we can master it!