Hooks compose, whereas side effects and memoized values sprinkled through component constructors and lifecycle methods do not.
For example, the equivalent of useEffect required calls inside of componentWillMount, componentDidUpdate, and componentWillUnmount. You try and make something like this re-usable and you’ll be leaking details of your implementation across the whole component via inclusion in these lifecycle methods, not to mention any data you’re shoving onto the component instance. But it’s still doable.
Now, what if you wanted to use this re-usable behavior inside of another re-usable behavior? It gets complicated fast! Now your library needs to expose the lifecycle-updating methods of the underlying library, leaking details all the way down. Hooks are opaque from the perspective of lifecycle, while still having access to all the same… hooks.
Oh ok. I'd agree Hooks compose much better then. But there was no attempt or consideration at compositional API for class based components besides getting rid of it entirely and then adding functions that hook into the nether nether.
> For example, the equivalent of useEffect required calls inside of componentWillMount, componentDidUpdate, and componentWillUnmount.
Yeah from what I recall this was the prime motivational example given in the React docs for introducing hooks. It's a legit problem. But hooks and getting rid of class based components is not the only solution. In classical OO are also well worn solutions along the lines of hooks, they just work with classes / objects with interfaces still. It's somewhat frustrating that this is never even considered.