With class components, my state/props are clearly defined within the constructor and/or PropTypes. This makes it easy to understand the overall architecture of a component. Functional components with Hooks don't have the same sort of structure and can be difficult to understand at a glance.
One of my gripes with Hooks is that listening for async state updates requires more code/complexity than w/classes. In a traditional class component, you can add a second, optional argument as a callback which is called when the state has updated:
setState({ myState: 'newValue' }, () => { this.doSomething(); });
With Hooks, that doesn't apply. The useState "set" function doesn't have a similar argument. setMyState('newState');
Instead, you need to use 'useEffect' with an optional argument: useEffect(() => { doSomething(); }, [myState]);
This leads to potentially having many "useEffects" scattered throughout the component.That said, this is just my experience with Hooks after a few months of working with them. It's entirely possible that I just haven't had enough experience with them yet.