В целом недостатки хуков можно разбить на семантические (синтаксис, основанный на соглашениях), анти-best-practice (смешение синхронного и асинхронного кода, сайд-эффекты в колбэках, раздувание чистых функций и смешение ответственности), сложностей в композиции (т.к. нет доступа к общим props и context, приходится передавать их в каждую функцию напрямую, что приводит к запутанному клубку), деградации перфоманса (т.к. приходится либо обкладывать многие части useCallback / useMemo, либо логика будет пересоздаваться на каждый ререндер и не будет работать сравнение по ссылкам).
В классах же:
- инкапсулированная логика с методами, в которых уже есть доступ к props, context и другим методам
- чистые render-функции
- человекопонятный жизненный цикл
- простота установки переменных (ref / не ref)
- одинаковые функции типа this.handleChange без оборачивания в дополнительный useCallback (бонус — легкость удаления обработчиков вроде addEventListener)
- возможность применения декораторов в @-синтаксисе как глобально к классу, так и к методам