Use when a component talks to the backend - go through the typed api client, type every response, and handle loading, success, and error states explicitly
Scanned 9/23/2026
npx -y skills add makifbaysal/tasktrooper --skill api-client-integration --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Api Client Integration?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/makifbaysal-api-client-integration)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: api-client-integration
category: frontend
description: Use when a component talks to the backend - go through the typed api client, type every response, and handle loading, success, and error states explicitly
tech_stack: React
---
# API Client Integration
## Overview
Every remote call is three states, not one. The recurring defects are raw `fetch` scattered in components, untyped responses, and errors swallowed into `console.log` while the UI half-updates.
**Core principle:** One typed client, three states (loading/success/error), no swallowed errors.
## Rules
- **Go through `web/src/api.ts`** helpers — never raw `fetch` in components.
- **Type every response** with an interface matching the backend JSON. A contract change starts by updating the interface so the compiler finds every affected usage.
- **Handle all three states:** loading (visible feedback), success, and error (toast with an actionable message).
- **Never swallow errors** into `console.log` — surface them to the user and keep the UI consistent (no half-updated state on failure).
- **Debounce** user-driven queries; cancel or ignore stale responses when inputs change quickly.
## Worked Example
```tsx
// ✅ typed client call, three states, no half-update on failure
const [state, setState] = useState<Loadable<Task[]>>({ status: "loading" });
useEffect(() => {
let active = true;
api.listTasks(projectId) // typed helper from api.ts
.then(tasks => active && setState({ status: "ok", data: tasks }))
.catch(err => active && setState({ status: "error", message: err.message }));
return () => { active = false; }; // ignore stale response
}, [projectId]);
if (state.status === "loading") return <Spinner />;
if (state.status === "error") return <ErrorView message={state.message} />;
return <TaskList tasks={state.data} />; // success only
```
The `active` flag drops a stale response when `projectId` changes; the error branch shows a real message instead of leaving a spinner or a half-list.
## Common Mistakes
- Raw `fetch` in a component.
- Untyped/`any` response.
- Only rendering the success path — no loading/error.
- `catch(e => console.log(e))` with the UI left inconsistent.
- No stale-response guard on fast-changing inputs.
## Red Flags
- `fetch(` inside a component file.
- A remote call with no error UI.
- A toast that says "error" with no actionable message.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!