API Integration Patterns
On this page
Adapter Layer Model
- UI should not call fetch everywhere.
- Centralize API calls in a thin client module.
- Map DTO to ViewModel before storing in UI state.
Core Contracts
- Request: typed input, explicit headers and auth policy.
- Response: validated DTO, mapped ViewModel.
- Error: normalized shape across endpoints.
- Telemetry: request id and timing attached for debugging.
Error Normalization Shape
type ApiError = {
kind: "network" | "http" | "timeout" | "parse" | "auth";
status?: number;
message: string;
fieldErrors?: Record<string, string>;
requestId?: string;
};
Cancellation and Race Safety
- Cancel in flight requests on route change when results are no longer relevant.
- Ignore stale responses to prevent UI rollback.
- Use single flight for deduped loads when multiple components request same data.
Example: AbortController Pattern
async function fetchJson(url: string, signal: AbortSignal) {
const res = await fetch(url, { signal });
if (!res.ok) throw new Error("http");
return res.json();
}
function useUsers(query: string) {
const [state, setState] = React.useState({ status: "loading" } as any);
React.useEffect(() => {
const ac = new AbortController();
async function run() {
try {
const data = await fetchJson("/api/users?q=" + encodeURIComponent(query), ac.signal);
setState({ status: "ready", data });
} catch (e) {
if (ac.signal.aborted) return;
setState({ status: "error", message: String(e) });
}
}
run();
return () => ac.abort();
}, [query]);
return state;
}
Waterfall Prevention
- Centralize route level data loading where possible.
- Batch requests or load in parallel if there are no dependencies.
- Avoid nested components each fetching its own data sequentially.
Failure Modes
- DTO leakage into UI components causes breakage on backend rename.
- Inconsistent error shapes create scattered error UI.
- Stale responses overwrite newer state, causing flicker and rollback.
- Retry without caps creates request storms during outages.
Production Checklist
- API adapter layer exists and is the only place calling fetch.
- DTO mapping and validation occurs before state updates.
- Error normalization is consistent across endpoints.
- Cancellation and stale response guards are implemented.