Not true, see Gaeron's direct reply in the thread you linked to, that's been the standard for 3 years and works like a charm - useEffect specifically is the hook for handling async functions ("impure effects").
Notice the words "pass to useEffect" in the parent comment, and the code snippet in the grandparent they are commenting on. The type of the callback function that useEffect accepts is () => void rather than () => Promise<unknown>. What's not true about that?
I reworded it to make it a bit more clear (at least, I thought so) — "pass an async function to useEffect", meaning the argument supplied to useEffect itself, rather than "use directly within" which is ambiguous. Re-added "directly" to hopefully make even more clear. Sorry for the confusion!
I usually use an IIFE to encapsulate the async block inside the useEffect. Works like a charm!
True, you cannot do that in useEffect, it will throw you error. And probably your linter will tell you. You can't even use your own or third party hooks in side useEffect. This also throw error I don't know why?
Because you could be nesting hooks, which would bring all sorts of weird behavior.
you're right, good catch. Usually it's the TS compiler that prevents me doing that.