Three buckets
Ephemeral UI (modals, hover) stays local. Server data belongs in a fetch/cache layer. Filters and pagination often belong in the URL so links are shareable.
If two distant trees need the same ephemeral state, lift it — or use a small store. Do not invent a global store for a single toggle.
Derived state is not state
If you can compute a value from props or existing state, do not sync it into another useState. Derived values go stale and cause loops.
Effects are for syncing outward
useEffect is for talking to the outside world (subscriptions, document title, analytics) — not for transforming data you already have. Transform during render when possible.