The naive useEffect fetch
Start with what works for a one-off: fetch on mount, store in state, render.
function User({ id }: { id: string }) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetch(`/api/users/${id}`).then(r => r.json()).then(setUser);
}, [id]);
if (!user) return <Spinner />;
return <div>{user.name}</div>;
}
This is fine for a quick prototype. It's wrong everywhere else: no caching, no dedup, no error state, no cancellation. Open the page twice in adjacent tabs and you double-fetch. Navigate away mid-flight and you setState on an unmounted component. We'll fix all of that, one footgun at a time.
