Sorry for being pedantic, but the first example could be rewritten to extract the pattern into a higher level hook, eg useNotifications. One way to simplify components before reaching for store libraries. The reusable hook now contains all the state and effects and logic, and the component is more tidy.
function Dashboard() {
const { user } = useAuth();
const {loading, error, notifications, undreadCount, markAsRead} = useNotifications(user);
if (loading) return <Skeleton />;
if (error) return <p>Failed to load: {error}</p>;
return (
<div>
<h1>Dashboard ({unreadCount} unread)</h1>
<StatsCards stats={stats} />
<NotificationList items={notifications} onRead={markAsRead} />
</div>
);
}
Working with multiple teams in a large project, hooks can be a nightmare to maintain.
I see 7x layers deep of hooks, with no test cases to support them. Some of the side effects are not properly tested, and mocks that abstract away the whole implementation means the test case only works for certain scenarios.
FWIW this scenario might be an outlier in large projects, considering how some developers prefer to "just wrap the hook in another hook, and not worry about its internals".
That's a valid concern. I've seen some hard to grok hooks with polling, async stuff, hard to follow logic, etc. Like with anything, need to have taste, it's easy to dump too much into one hook and like you mention, it gets hard to follow what gets triggered when.
I was wondering if I was crazy for thinking "how is what he's suggesting different than just putting that 'class' into a hook function?" I'm glad to see someone already wrote it up, kudos.