Data Fetching & Server State
Request, loading, success or error, render — and the parts that only show up in production: cancellation, deduplication, retries, pagination and background refresh.
Request, loading, success or error, render — and the fact that `fetch` resolves happily for a 500, has no deadline, and hands you a body you still have to parse.
An interaction has at least four states and usually five. The missing failure branch is the most common defect in frontend code, and empty is not loading.
`AbortController`, unmount, and the `AbortError` that must never be shown to a user — because abandonment is not failure.
In-flight coalescing and caching are two different mechanisms with two different windows. Confusing them is why "we have a cache" does not stop the thundering herd on mount.
Retrying a non-idempotent mutation is a correctness bug wearing resilience as a costume. Retry only what is safe, with backoff, jitter and a cap.
Offset gives you jump-to-page and gives you duplicates under insertion. Cursor gives you stability and takes away page numbers. Pick from the UI you owe, not from the API you were given.
It has freshness, a cache, invalidation, refetching, synchronisation and an authority that lives somewhere else. Copy it into component state and it starts diverging immediately.