Chapter 4: Bringing the Frontend to Life! API Integration, Axios, and Asynchronous Magic
In the previous chapter, we created a beautiful table with real-time search functionality using mock data. But when you showed the webpage to your boss, they asked: "Why are all the names Wang Xiaoming and Li Dahua? Where are today's punch records?"
That's right - the frontend data was hardcoded and unaware of real-world changes.
In reality, frontend webpages must actively request the latest data from backend servers (like our FastAPI backend). This bridge between frontend and backend communication is called API (Application Programming Interface).
๐ฏ Chapter Goals
- Understand the underlying logic of frontend-backend communication: What is an HTTP Request? What is an API?
- Learn about the industry's most powerful HTTP client package:
axios. - Master React's
useEffectHook to implement "automatically fetch data when page loads" functionality. - Handle "Loading" and "Error" states - essential skills for professional frontend developers.
๐ What are APIs, Fetch, and Axios? (Plain English Explanation)
Imagine dining at a fancy French restaurant:
- You (Frontend): You browse the exquisite menu (UI interface) and decide what to order. But you can't just walk into the kitchen to get your food.
- Kitchen (Backend Database): Where all the fresh ingredients (punch records) are stored, with chefs (FastAPI) preparing the dishes.
- Waiter (API): You give your order to the waiter, who goes to the kitchen and brings your food. This "ordering" and "serving" process is calling an API.
In JavaScript, the most basic way to call the waiter is using the native fetch() function.
However, fetch is somewhat verbose, requires extra steps to handle JSON format, and isn't very smart at error interception.
That's why frontend developers worldwide prefer using a third-party package called Axios, which makes data fetching extremely elegant and comes with powerful built-in features.
๐ Hands-on: Installing Axios and Creating API Instance
๐ฅใVibe Prompt Practical Spellใ
I'm developing a React (Vite) project that needs to connect to a local FastAPI backend API.
1. Give me the npm command to install axios.
2. Industry standard practice is to separate API connection settings. Please help me create an api.ts file in src/utils/.
3. In api.ts, use axios.create to make an instance with baseURL set to 'http://localhost:8000/api' and timeout set to 5000 milliseconds.
The AI will instruct you to open terminal and enter:
npm install axios
And generate a perfect API module configuration:
// ๐ src/utils/api.ts
import axios from 'axios';
// Create Axios Instance
// Benefit: You won't need to type full URLs every time - just use '/punches'!
export const apiClient = axios.create({
baseURL: 'http://localhost:8000/api', // FastAPI local URL
timeout: 5000, // If the waiter takes over 5 seconds, consider the order failed (timeout)
headers: {
'Content-Type': 'application/json',
},
});
โณ Combining useEffect: Fetching Data on Page Load
Now that we have apiClient, when should we call it?
Answer: When this Data Table component first appears on screen!
In React, to control "do something when first appearing", we use the powerful useEffect.
๐ฅใVibe Prompt Practical Spellใ
Please modify the previous DataTable.tsx to replace mockData with real API calls.
1. Import the apiClient we just created.
2. Use useEffect to call GET /punches API when the componentใmountsใ.
3. Handle 3 states: data, isLoading (default true), and error message.
4. When rendering: if isLoading is true, show a spinner or "Loading..."; if error exists, show red error alert.
5. When data is received, set the backend response array into data state.
The AI will generate this professional-grade async/await code:
import { useEffect, useState } from 'react';
import { apiClient } from '../utils/api';
export default function DataTable() {
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// ๐ก useEffect with empty array [] means this runs only once when component first appears!
useEffect(() => {
const fetchPunchRecords = async () => {
try {
setIsLoading(true);
// Order from waiter (API) by requesting /punches data
const response = await apiClient.get('/punches');
// Waiter brings food to our table (State)
setData(response.data);
} catch (err) {
console.error("API call failed", err);
setError("Failed to fetch punch records. Please check if server is running.");
} finally {
// Whether success or failure, always turn off loading animation!
setIsLoading(false);
}
};
fetchPunchRecords();
}, []);
// Render fallbacks: ternary state handling
if (isLoading) return <div className="p-10 text-center animate-pulse">๐ก Fetching data from server...</div>;
if (error) return <div className="p-10 text-center text-red-500 bg-red-50 rounded-lg">โ {error}</div>;
return (
// ... Render your beautiful table here with real data ...
<div>
{/* Table UI omitted... */}
</div>
);
}
๐ผ [Business Scenario] Why Skeleton Screens Matter
In our implementation, we added an isLoading state. This is crucial when selling systems to enterprises.
During the 0.5 seconds while waiting for backend data, if the screen is blank, users might think the site crashed and frantically refresh, doubling API requests and potentially crashing your server.
This is called User Perceived Latency.
As a professional developer, you can tell AI in your prompt: "When isLoading is true, give me a Tailwind Skeleton Screen effect" - showing gray, shimmering placeholder blocks.
Users seeing these will think "the system is working", extending their patience from 0.5s to 3s. This small UI detail separates junior from senior engineers!
โ Chapter Summary
You've successfully learned core frontend work: requesting data from backend, gracefully handling loading/errors, and displaying real data!
But when you first run this code, you likely won't see data - instead encountering every frontend developer's nemesis: CORS Cross-Origin Blocking Error.
Don't worry! Every engineer has faced this. Next chapter, we'll demystify CORS in plain terms and teach you how to solve it instantly with prompts!