Fetching API and CORS
Introduction
React apps load data from REST APIs with fetch. In development, Vite runs on port 5173 while FastAPI or Flask runs elsewhere—browsers enforce CORS. This chapter covers env URLs, Vite proxy, typed clients, loading/error UI, JWT headers, and custom hooks—parallel to Vue Fetching API.
Prerequisites
Environment Base URL
.env:
VITE_API_URL=Empty with proxy—use relative /api/... paths.
src/api/client.ts:
Code explanation:
- Only
VITE_*vars are exposed to the browser - Never put server secrets in
VITE_variables
Vite Dev Proxy
vite.config.ts:
Frontend:
const posts = await apiGet<Post[]>("/api/v1/posts");Browser sees same origin localhost:5173; Vite forwards to the API.
See Flask CORS and Frontend when not using a proxy.
CORS on the Backend
Cross-origin without proxy requires API CORS headers.
FastAPI — Middleware and CORS:
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"],
allow_methods=["*"],
allow_headers=["*"],
)Django: API auth and CORS.
Production: restrict origins to your real frontend domain.
Authenticated Fetch
usePosts Hook
src/hooks/usePosts.ts:
Three-State UI
axios (Optional)
npm install axiosimport axios from "axios";
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL,
});
api.interceptors.request.use((config) => {
const token = localStorage.getItem("token");
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});This track uses fetch by default—axios is a team preference.
Hello Code Backend Links
| Backend | Chapter |
|---|---|
| FastAPI | REST CRUD project |
| Django | Blog REST |
| Flask | CORS integration |
Blog reader project: chapter 23 — same API as Vue 24.
FAQ
fetch in useEffect vs loader?
Both valid—useEffect + hook is flexible; router loader colocates data with route.
POST JSON?
await fetch("/api/v1/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title }),
});CSRF with cookie auth?
Send CSRF token header—Bearer JWT in header avoids cookie CSRF for SPAs.
OpenAPI types?
Generate with openapi-typescript—optional advanced step.