Have you seen the ReactConf talk on hooks? [1] It's absolutely worth the watch, even if you're somewhat familiar with hooks. They go through the pitfalls of class-based components and how hooks solve them.
It more-or-less boils down to: 1. class-based components force your lifecycle logic to live in disparate locations. 2. Class-based hooks are obtuse with hidden gotchas whereas pure functions tell you exactly what they're doing. 3. A whole class of unergenomic solutions disappears when you use hooks.
I'd argue that hooks didn't really make anything better, they just replaced the pitfalls with different obtuse pitfalls and unergonomic solutions.
Hooks have their share of weird issues; they explode if they're called in a different order/number from how they were called the first time the component rendered (making them not at all pure functions), and it's super easy to screw up the dependency array to useMemo/useCallback (so either your hook is useless and re-installs the event handler on every render, or you get stupid "the callback had a stale copy of the state" bugs not possible with class-components).
I've also seen my fair share of situations where what would have been a this.setState with a callback becomes a tangled mess of useStates and useEffects, or someone bends over backwards to try and avoid re-installing an event handler every time one of the props or state variables it uses changes.
I feel of all the arguments against hooks, the whole “order of hooks” thing is the thinnest. You just learn about it and then it’s not a problem again.
I definitely get that there are some more complex cases where you have to jump through a couple of useRef hoops to do what you need. On balance though, I think the way the behaviour becomes declarative is worth the trade off.
Coming from the FP world, hooks are a terror because they break all the nice rules functions are supposed to uphold. Hook components don't necessarily return the same value when given the same arguments, making them impure (stateful). The benefit of function components IMO has always been that you can use the function scope as a container for pure, stateless rendering logic. With the introduction of hooks I can no longer ensure that.
Nothing stops you from using pure function components, and you should where possible. But eventually, you need to hold state somewhere. You don't need to put it in your components, but you do need to deal with it. If anything, hooks are a nice middle ground where the behaviour becomes declarative.
My personal opinion is that state should be contained in some sort of class or data structure, separate from functional architectures where the notion of state is generally avoided. So my usual suggestion would be to use either a class component (or redux or insert favorite state mgmt solution here) for your state, and then inject the state as props to your function components
That's fine, you can use React's Context API and reducers just like Redux, for which the useContext and useReducer hooks exist. Then it's just like Redux, inject a Provider and Consumer and you're good to go.
They don't, but before I could look at a function component and go "ah, a nice stateless component" whereas now I have to wonder whether the _function_ contains _state_
The issue I have with the "rules of hooks" is that it makes some previously trivial things cumbersome at best, and downright complicated at worst. For a quick example, something as simple as mapping an array onto a series of elements with a callback requires (as far as I can tell) that the inner element be broken out into its own component that calls `useCallback`, since you can't create a unique callback for each item in the parent.
I don't quite get the obsession with the order of hooks... You call all the hooks in your component function and don't optionally do so. In the end, if you're optionally calling different hooks differently in the same component, you're probably doing something wrong, and/or they should be separate components.
I've found that the hoop jumping type stuff, while potently annoying, can at least be abstracted into a custom hook (and then mocked in tests) easily so that the code is clean.
It's not classes themselves, it's the lifecycle methods, the constructor, this, state, and it all interacts. Hooks let you do more or less the same thing, but IMHO with a simpler and clearer API.
You have more control too. Look at the parameters to useState to see what I mean.
I feel like there is an alternative world that we aren't seeing, where instead of changing the paradigm, the react team redesigned the class API instead.
The class API lifecycle methods are kind of a mess, and useEffect() seems like a more convenient abstraction. But I could imagine replacing the lifecycle methods with hooks that are added at object construction and get similar benefits. I wonder if the problem is not so much classes, but just the API that happened to evolve.
How are your functions pure if inside them you call `useEffect`, `useState` ? Where is pureness when at first look they generate side effects, or am I missing something ?
Sure, if you define a function called useWhatever that doesn't actually call any hooks, that might be a pure function. But the restrictions described in https://reactjs.org/docs/hooks-rules.html are not restrictions that pure functions have.