That's a good tradeoff in statically typed language. I'll take composition over inheritance and abstract out the interfaces I want to maintain, rather than worrying about who has implicitly started to depend on an incidental interface.
This is yet-another-example of why JS has a lot of growing left to do. If a language doesn't require you to define types (and enforce them), you get these messy dead-ends that are used to rationalize even worse solutions.
I also don't think it is an accident that React starting truly "in house" embracing Typescript until after Hooks. (React was always Flow typed, so far as I'm aware, but the switch in "guiding" type systems at least in terms of public stances is much more recent, and I believe post-Hooks.) Hooks deserve a lot of criticism. They are absolutely a compromise even to their creators. (The "Hook Rules" seem to be something that the creators had wished to embody in a type system rather than a linter but didn't have the tools in current Typescript and the linter approach is obviously a compromise.) But they are well-typed in Typescript in ways that HOCs never were. Their APIs are entirely explicit and well-defined.
Those APIs are "weird" to traditional OO developers and OO purists, but those APIs are designed for static typing and accountability to type systems (Typescript especially now).
But a lot of the issue with HOCs was that they were so dynamic and difficult to properly type - simple cases would work but be very complex, and complex cases were almost impossible without dropping down into `any` types or type assertions somewhere along the way.
In contrast, hooks work much better from a typed perspective, but also from the perspective of providing composition over inheritance - it's much easier to compose multiple hooks to create new functionality than it was to compose multiple HOCs.
That's a good tradeoff in statically typed language. I'll take composition over inheritance and abstract out the interfaces I want to maintain, rather than worrying about who has implicitly started to depend on an incidental interface.
This is yet-another-example of why JS has a lot of growing left to do. If a language doesn't require you to define types (and enforce them), you get these messy dead-ends that are used to rationalize even worse solutions.