Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You use the word "simple," but it sounds like you mean something more like "familiar." That's not a knock; familiarity is important when designing an API that thousands of developers are going to use every day.

But as you can see by the blog post, there are tradeoffs between doing something the way people are familiar with, versus a different way that's less familiar, but has different capabilities that might fit the problems better.

Classes map to certain use cases very well; for instance, there's no Hook for "componentDidCatch" or any other error handling.

That being said, you are not losing anything. The tools are simply different (although the old tools are still there, too!).

As the blog post goes into, you can still implement the same _behavior_ as you did with componentDidMount/componentDidUpdate, but with Hooks you can formalize the different patterns you would find when using those methods into a custom hook that you can reuse. This wasn't possible before.

shouldComponentUpdate can be easily replaced with React.memo, a higher-order component that takes a function that compares the previous props to the new props and returns whether they are the same. Wrapping it in React.memo without a custom comparator is the same as PureComponent.



> You use the word "simple," but it sounds like you mean something more like "familiar."

Guilty as charged. I needed to hear that :)


To play devil's advocate a bit: I don't think you were wrong the first time.

I mean, as long as hooks are strictly an addition, it's easy to argue greater simplicity without. That's kind of trivial though, so I would ask how thematically related they are.

If they both clearly stem from the same set of underlying principles and motivations, I think it's fair to say the addition is not substantially a complication. But is that the case for hooks? (I don't know—haven't looked into them yet :)

But maybe the confusion is whether the additional complexity we're talking about is in React itself, or in the systems being built with react. In that case, old React may be simpler, but the code it produced was more complicated; or React with hooks may be more complicated, but the code you write with it is now simpler.


I'd argue it's more complicated by way of how much confusion I see with newbies. The old class-based lifecycle+methods was pretty straightforward - it only looked complicated at a glance. Hooks on the other hand do enough magic in the background that each one seems to come with its own set of misconceptions that have to be corrected.


The ironic thing is that hooks are marketed by the react docs as being the solution to avoiding the "difficulty" newbs have with classes.

Which I (as a proponent of hooks) think is fucking batshit insane, and clearly shows the disconnect of the React devs from their user base.

Teaching beginners how to code, and how to use React, is a large part of my job. And I can say with absolute conviction that the React team is wrong about this. The 'hooks' whiteboarding session has gotten me far more blank stares than the 'classes and lifecycles' one ever has.

Having said that, as a senior dev with a ton of React projects under my belt, I definitely prefer the hooks paradigm after using it in a few projects. It makes for cleaner code, and certain concepts are much easier to reason about with the hooks model. Just don't ever expect it to give you a cleaner on-boarding process. That's not at all where the benefit lies, despite what the docs tell you.


Should probably dump it here myself: My experience is mainly with co-workers (years of experience) and new hires (just out of college/bootcamp) who can code, but haven't yet used React.


Yeah my experience is pretty much all with beginners (usually fresh out of a bootcamp or college, or switching from tangentially related industries like CSE).

I'd be interested to see how someone who was a beginner but learnt via FP would grasp each approach. I've never met one in the wild though, it's not like bootcamps start with Haskell.


Are they a strict addition? I never learned class-based components. I literally never think about “mounting”.

I also never think about “updates”. I do think about rendering as something that happens continuously all the time outside my control.


I think the old way is simpler in the sense of building on fewer concepts, and therefore allowing an easier learning curve, if you grant that understanding the React component lifecycle is required and inevitable. Once you understand the lifecycle, running code when certain lifecycle events happen is a very small, concrete conceptual leap. Names like "componentDidMount" tie directly into your fundamental understanding of React. If using them to maintain state forces you to deepen your understanding of the component lifecycle, that effort will pay dividends when you have to debug, optimize, understand someone else's wacky code, etc.

Hooks, on the other hand, have to be learned as an additional and separate concept. In fact, each hook has to be learned. You won't have a clue what "useState" and "useEffect" do just by having a knowledge of React fundamentals. If using hooks allowed developers to avoid knowing the React component lifecycle, an argument could be made that they provide a simpler alternative, but I don't think anybody is going to get very far without being forced to learn about the component lifecycle. If someone were to say, "The React lifecycle is hard to understand, so use hooks instead," that would be a false promise. Hooks are something extra to learn, not an alternative to understanding the lifecycle. To the extent that a programmer can avoid understanding the lifecycle by using hooks instead, they are just putting off that learning curve until they have to traverse it later, probably under the pressure of debugging some nasty issue.

Hooks seem to win from another perspective, though, which is that by accepting the cost of adding this new concept to your mental model, you can write simpler-looking code that is easier to keep error-free. To me, that's the trade-off. Hooks are an extra complexity to understand, and each new hook can encapsulate arbitrary complexity and behavior that isn't obvious from reading code that uses them, but the code that uses them can be more concise and perhaps easier to read and keep correct.


I think this also falls into the same familiarity trap as the parent.

Let me preface this by saying that I think it's not necessary to conflate the "lifecycle methods" with the component lifecycle in itself, and I disagree with the premise that the methods are a fundamental concept of React. Of course, this is how people were historically taught, but it is entirely possible to conceptualise and understand the lifecycle of a React component without even knowing about lifecycle methods, just in terms of how useEffect works, for instance, and this is how a lot of people using hooks today think. It is entirely possible to understand how re-renderings are triggered and stuff like that without even knowing about class components and lifecycle methods.

So, hooks might seem like an additional concept to people used to class components and lifecycle methods, but that's just because of familiarity. For people learning hooks first, the opposite is true just as well.

IMO this paradigm shift in thinking is also essential for people used to class components that want to be more productive in codebases with mostly hooks. I haven't thought about componentDidUpdate and friends in months.


> I think the old way is simpler in the sense of building on fewer concepts, and therefore allowing an easier learning curve

I would disagree with that premise. From my own experience and from having mentored developers on class components (so like ~7 data points), I'd say it's far easier to reason about state flow with hooks than lifecycle methods. That's an important point, because I see far more bugs with incorrect or incomplete state flow than I see with component lifecycles.

Hooks are simply easier to reason about. With hooks, you read the code top to bottom. Then, something changes either with the data or in response to user input, and then you read the code top to bottom again with that new state.

The only learning curve there is to understanding the basic premise of hooks is that "if this value is different from the last time you read the code top-to-bottom, then re-read/execute this code block"

> If using hooks allowed developers to avoid knowing the React component lifecycle, an argument could be made that they provide a simpler alternative, but I don't think anybody is going to get very far without being forced to learn about the component lifecycle. If someone were to say, "The React lifecycle is hard to understand, so use hooks instead," that would be a false promise.

That is exactly my premise, and I don't think it's a false one. Since moving to hooks, I can't remember the last time I had to care about the React lifecycle. Again, the mental model is "Read the code top to bottom; something changes; read the code from top to bottom" ad infinitum.

Yes there are situations where class components provide more intimate control (componentWillUnmount comes to mind since I'm not aware of a hook for that), but are we really optimizing the majority of our code for exceptional cases?

Another data point: I haven't seen functional components turn into a complete mess from inattentive developers in the same way I've seen class components turn into indecipherable setState tangled messes. The only time I've experienced the pressure of sifting through component lifecycles under the pressure of debugging a time-sensitive production isssue is because I was using component lifecycles in the first place. It's a moot point.


> Yes there are situations where class components provide more intimate control (componentWillUnmount comes to mind since I'm not aware of a hook for that), but are we really optimizing the majority of our code for exceptional cases?

The return value of invoking React.useEffect’s first parameter is a cleanup function which serves this purpose.

Everyone in this thread is ragging on core concepts like useMemo or useEffect. Once you know these core functions, you’ve learned all the magic. Then you can write spells of your own.


I think the argument that hooks lose on simplicity (as opposed to familiarity) can hold water if you think about it this way: sure procedural code is very familiar to most JS devs and consuming hooks indeed feels procedural. Ok. BUT. Reasoning about the rules of hooks when you're writing non-trivial hooks, that's not familiar, and it's not simple either. At my day job, there have been some debates about supporting Suspense composition and the semantics are very difficult to reason about because not only you have to keep in your head what the procedural code actually does, but you also need to keep track of whether e.g. certain flavors of certain expressions violate the rule of hooks. The term "magic" is a very appropriate way of describing how hooks feel in this context.


Thanks for sharing. As someone who's done React for years (and webdev since 1998) but yet to do more w/ Suspense than read about it, it seems to me like [Suspense + Hooks] is an area where we're still some distance from solid idioms and established best practices. Maybe the APIs will undergo further refinement before that happens. As for magic (which, if good, decomposes into sane primitives), you might be right. But in general I appreciate the degree to which React's evolution over time has trended towards reducing the cognitive overhead of lifecycle concerns and state mgmt solutions. (To say nothing of reconciliation, which I'm perfectly happy to enjoy, whether it's voodoo or not.) /ramble


>Classes map to certain use cases very well; for instance, there's no Hook for "componentDidCatch" or any other error handling.

>That being said, you are not losing anything. The tools are simply different (although the old tools are still there, too!).

Well... no, you clearly are losing something. You might not use it frequently but it's a pain in the ass when you do need it.


Classes are not verboten :) I typically create an error boundary that wraps my app/feature/etc. with a fallback component and call it a day.


> familiarity is important when designing an API that thousands of developers are going to use every day.

I'd argue it's less important for an API people use every day than it is for an API used once a month. Things should be designed for people with more than one week of experience with it, even if it makes adoption slightly tougher!




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

Search: