- EN
- ID
Master Table of Contents
- See full index in 01. Introduction
Who this chapter is for
- Learners building apps that rely on external APIs in daily flows
- Beginners who want request handling that is stable and easy to debug
- Anyone tired of random loading bugs and unclear error states
What you’ll learn
- How to design a clean API service layer
- How to model loading/empty/error/success UI states clearly
- How to add basic resilience: timeout, retry, and lightweight caching ideas
Why this topic matters
Most frontend issues appear at the API boundary: bad responses, delayed network, and inconsistent data shape.
A consistent integration pattern makes your app feel reliable and makes debugging much faster. This is one of the highest-value patterns for production-ready React apps.
Core concepts
UI states
- Loading while waiting
- Empty when data has no items
- Error when request fails
- Success when data is ready
Treat these states as first-class UI behavior, not afterthoughts.
Service layer
- Keep fetch logic separate from UI components
- Standardize response and error mapping
Service layer keeps components focused on rendering, not HTTP details.
Step-by-step walkthrough
Step 1 — Create API client functions
Group endpoint calls in one services folder with clear function names.
Step 2 — Build request state model
Track request lifecycle explicitly with isLoading, error, and data.
Optional: add status: "idle" | "loading" | "success" | "error" for cleaner UI branching.
Step 3 — Improve resilience
Add timeout and limited retry for transient failures (not for every error type).
Map technical errors into messages users can actually act on.
Practical examples
Example 1 — Service function shape
export async function fetchMovies(query: string) {
const response = await fetch(`/api/movies?q=${encodeURIComponent(query)}`);
if (!response.ok) throw new Error("Failed to fetch movies");
return response.json();
}
Tip:
- Keep endpoint-specific logic here, not inside UI components.
Example 2 — Component state handling
- Set loading before request
- Set data on success
- Set error on failure
Real-world rule:
- Always clear stale error/data state before starting a new request.
Common mistakes and how to avoid them
- Calling
fetchdirectly in many components -> centralize service layer - Ignoring non-200 responses -> always check
response.ok - Showing raw technical errors to users -> map to user-friendly messages
- Mixing request logic with heavy rendering logic -> separate concerns cleanly
Mini Project
- Build a movie explorer with:
- search page,
- detail page,
- loading/empty/error/success states,
- timeout handling for slow requests,
- simple retry button for failed requests.
Bonus:
- Add a small in-memory cache to avoid repeat requests for the same query.
Quick practice
- Create typed API response model
- Add timeout handling for one endpoint
- Add retry logic for one transient error case
- Write one helper that maps technical errors to friendly UI text
Key takeaways
- API integration needs architecture, not just “quick fetch calls”
- Service-layer separation keeps components clean and maintainable
- Clear state + friendly error handling directly improves user trust
Next step
Continue to [15. Testing in JavaScript/TypeScript/React].
No Comments