OP has the same complaint as everybody about hooks: when I inline a bunch of code in the component it isn't readable. This is because they aren't using hooks fully. You're supposed to break your logic out of the component into custom hooks. Sometimes those hooks are reusable, sometimes they are just implementation details for a single component. Just using the built in hooks isn't "using hooks" any more than calling built-in functions is "using functions".
The component the OP winds up with wouldn't pass code review on my team, either the hooks version or the class one. It's took long and doing too much. In fact, one of the things op misses about class components is the ability to easily have your components do too much, they lament the loss of custom render functions (eg this.renderList()), even acknowledging that those functions should be components. Good luck testing a mega component like that.
There is a learning curve to using hooks gracefully, for sure, and the fact that OP claims not to know when a useEffect is going to run compared to componentDidUpdate is proof they aren't there yet. There's literally a list of values at the end of useEffect that define exactly when it's going to run.