“hooks make for more straightforward and concise code”, “easier to learn”
Proceeds to pass an empty array for no apparent reason* to a function in the first example. The later explanation completely ignores mutability and what it means for the type of value you can use as a dependency.
Hooks are nice for small components, but overall haven’t improved DX over classes much, and introduced a ton of new concerns. Yes, it makes composition easier. It also makes it harder to reason about component lifecycle when state changes are distributed among a dozen little functions with slightly different update semantics.
* I am familiar with how hooks work, am highlighting the implicit complexity
> Hooks are nice for small components, but overall haven’t improved DX over classes much, and introduced a ton of new concerns.
Composition itself is a huge DX improvement.
> It also makes it harder to reason about component lifecycle.
I would argue that it is the same if not better than class based components. One of the amazing things about hooks is that you can ignore all of the hook updates and just treat the values returned by them static to see how the rendering will happen at a particular instance.
For simple states hooks are the same if not better, I would say almost probably better.
For complicated states where you need 4+ hooks - well in that case most of the time refactoring is needed but there are cases where it should not be refactored and I have a certainty something could be done much easier with the old class based way of doing it, but then I would have to deal with people in PR who say we must use hooks for everything.
Agreed. I'm a senior dev and I think they're a nightmare to follow, even once you understand how they work. The combinatorial complexity of all the different implicit rules is astounding, and there's an entire armory of foot-guns. The lint rules help, but are intrinsically limited by working at a syntax level, not a value level; it's very easy for things to slip past them.
Recently at my job we had a senior engineer (me), a lead engineer, and a junior engineer (all of us familiar with how hooks work), looking at a 10-line hook in the codebase, and we couldn't collectively figure out whether or not it actually did anything without running it to see how it behaved.
If that's not an indictment of hooks, I don't know what is.
I'm no advocate of OOP, but React components are one of the few places where I've had a very good experience using classes
"looking at a 10-line hook in the codebase, and we couldn't collectively figure out whether or not it actually did anything without running it to see how it behaved."
While hooks do have problems, this could be said about pretty much any programming language or framework, especially when it comes to code that allows for better reusability. In this instance, I suspect it's more of an indictment of the original programmer instead of hooks.
It wasn't super elaborate or poorly-written, though it was kind of subtle. It had to do with letting you do something without triggering an update. What we couldn't tell is whether or not it was having the desired effect (or any effect at all) on component updates.
But that's just it: the nuanced ways that different hooks do and don't trigger updates are at the heart of what makes them hard to use correctly.
> Hooks are nice for small components, but overall haven’t improved DX over classes much
I think one of the best things about the transition to functional components and hooks is that you’re strongly encouraged to make ALL components small components. Class components tend to accumulate more and more functionality, which leads to interleaved logic and unmanageable complexity. If you keep all your components small, then functional components and hooks are better than class components, in my opinion. I admit, it can be a challenge to find the right patterns to build up complex functionality out of small, composable components, though.
You can put as much JSX in class components as functional ones. I've seen both of them being used to fit as much JSX as humanly possible, I don't think it matters at all which one is being used as the implementation doesn't care how much you put in it.
There’s a pattern I’ve seen in a lot of class components that doesn’t fit as well in a functional component: every time the component needs to render some new bit of JSX, create renderThing(), renderOtherThing(), etc, ad infinitum. These just don’t happen in functional components. Technically, you could create an inner function, but people just don’t seem to do it as much. They create a new component. Or at least, in my team, the resistance to breaking that stuff out to separate small components was much lower than with class components. It took very little effort in code reviews to push people towards small components and do it consistently.
Check out Surplus. It was "hooks" before the react team decided to implement a half-assed version of clocks.
I use surplus everywhere I'm allowed to, and it rarely bites me. It also allows me to develop pretty robust frontends quite quickly. The learning curve is a bit high, admittedly, but I think that's fine.
For the same reason some many frontend developers refuse to use typescript because "it adds bloat to the code".
And I have to admit, if your code is mostly concerned with checking if form fields are not empty before submitting, then you are probably fine with unstructured random chunks of code. I think it's parallel to Pythons success in certain niches.
But once you start building real application running in browser (or mobile, or even desktop these days, hello Teams), then pretending that untyped, unstructured and functional (if you even know what that means) is the best thing that happened since Touring then you're heading for a huge disaster.
Proceeds to pass an empty array for no apparent reason* to a function in the first example. The later explanation completely ignores mutability and what it means for the type of value you can use as a dependency.
Hooks are nice for small components, but overall haven’t improved DX over classes much, and introduced a ton of new concerns. Yes, it makes composition easier. It also makes it harder to reason about component lifecycle when state changes are distributed among a dozen little functions with slightly different update semantics.
* I am familiar with how hooks work, am highlighting the implicit complexity