Module 8
Fetching Data From an API
-
GET vs POST (Client-Side Only)
GET is for reading data. POST is for sending data (like form inputs). -
API Keys
Think of it like a password for accessing an API. We send it in headers or query params. -
How JSON Works Over the Web
JSON (JavaScript Object Notation) is the standard format for sending data over the internet:- Serialization: Converting JavaScript objects to JSON strings for transmission
// JavaScript object const user = { name: "John", age: 25, email: "john@example.com" }; // Serialized to JSON string const jsonString = JSON.stringify(user); // Result: '{"name":"John","age":25,"email":"john@example.com"}'
- Deserialization: Converting JSON strings back to JavaScript objects
// JSON string received from server const jsonResponse = '{"id":1,"name":"John","status":"active"}'; // Deserialized to JavaScript object const userData = JSON.parse(jsonResponse); // Result: { id: 1, name: "John", status: "active" }
- Data Transfer Process:
- Client creates JavaScript object with data
- Object is serialized to JSON string using
JSON.stringify()
- JSON string is sent over HTTP request
- Server receives JSON string and deserializes it
- Server processes the data and sends JSON response
- Client receives JSON response and deserializes it
- Why JSON? Universal format that works across all programming languages and platforms
- Serialization: Converting JavaScript objects to JSON strings for transmission
-
Breaking Down a Request
Every HTTP request has these key components:- URL: The web address where you're sending the request (e.g., https://api.example.com/users)
- Method: The type of action you want to perform:
GET
- Retrieve data (like reading a webpage)POST
- Send/create new data (like submitting a form)PUT
- Update existing data completelyPATCH
- Update part of existing dataDELETE
- Remove data
- Headers: Additional information sent with the request:
Content-Type
- Tells server what type of data you're sending (JSON, form data, etc.)Authorization
- API keys, tokens, or login credentialsUser-Agent
- Information about your browser/app
- Body (optional): The actual data you're sending (only for POST, PUT, PATCH requests)
- Query Parameters: Data added to the URL after ? (e.g., ?page=1&limit=10)
{ "url": "https://api.example.com/users", "method": "POST", "headers": { "Content-Type": "application/json", "Authorization": "Bearer your-api-key-here", "User-Agent": "MyApp/1.0" }, "body": { "name": "John Doe", "email": "john@example.com", "age": 25 }, "queryParams": { "page": 1, "limit": 10 } }
-
Async/Await Refresher + Axios
Fetch API: Built-in browser method for making HTTP requests
Axios: Popular third-party library for HTTP requests (more features)// GET request with fetch async function getData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('Error:', error); } } // POST request with fetch async function postData() { try { const response = await fetch('https://api.example.com/data', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'John', age: 30 }) }); const result = await response.json(); console.log(result); } catch (error) { console.error('Error:', error); } }
Key Differences:// GET request with axios async function getDataAxios() { try { const response = await axios.get('https://api.example.com/data'); console.log(response.data); } catch (error) { console.error('Error:', error); } } // POST request with axios async function postDataAxios() { try { const response = await axios.post('https://api.example.com/data', { name: 'John', age: 30 }); console.log(response.data); } catch (error) { console.error('Error:', error); } }
- Fetch: Built-in, requires manual JSON parsing, no automatic error handling
- Axios: Third-party, automatic JSON parsing, better error handling, request/response interceptors
-
Simple Flow Explanation
Client ➡️ Request ➡️ Server evaluates ➡️ Response ➡️ Client receives -
POST Requests & Testing Endpoints
POST requests are used to send data to servers (create, update, submit forms):- When to use POST: Creating new data, submitting forms, uploading files, authentication
- Data in Body: POST requests include data in the request body (not URL)
- Headers Required: Usually need
Content-Type: application/json
Use tools to test your API requests before coding:- Postman: Popular GUI tool for API testing
- Insomnia: Lightweight alternative to Postman
- Thunder Client: VS Code extension for API testing
- cURL: Command-line tool for making requests
📥 Download Postman (Free) Great for testing GET, POST, PUT, DELETE requests!
Live Example: Fetch Brewery Data
Click the button below to see a real fetch request in action. Open your browser's console (F12) to see the detailed steps!
TODO: Add an input field to let users search for breweries in any city!
Bootstrap and Tailwind CSS
-
Overview
Both are UI libraries that help you style without writing CSS from scratch. But why do we use them instead of writing our own CSS?- Time Efficiency: Pre-built components save hours of development time
- Consistency: Ensures your app looks professional across all pages
- Responsive Design: Automatically works on mobile, tablet, and desktop
- Cross-Browser Compatibility: Tested to work on all major browsers
- Best Practices: Built by experts with accessibility and performance in mind
-
Using Bootstrap CDN
No install needed, just link to the stylesheet like we did in this HTML. -
What is a CDN?
A fast network to load shared files (like Bootstrap) from servers close to the user. -
Bootstrap vs Tailwind
Bootstrap: Gives you pre-made components (buttons, cards, modals) that you can use immediately. Think of it like LEGO blocks - you get complete pieces that you can customize.
Tailwind: Gives you low-level utility classes that you combine to build anything. Think of it like individual LEGO pieces - you have complete control but need to build from scratch.
When to choose which:- Choose Bootstrap: When you want to build fast, need consistent components, or are new to CSS
- Choose Tailwind: When you want complete design control, need custom designs, or prefer utility-first approach
-
Semantic-based Class Naming
Tailwind's classes describe *what* it does (bg-blue-500
), not where. -
Real-World Benefits
- Faster Development: Build a professional-looking website in hours instead of days
- Team Collaboration: Everyone uses the same design system and components
- Maintenance: Updates and bug fixes are handled by the framework team
- Performance: Optimized CSS that loads quickly and efficiently
- Accessibility: Built-in support for screen readers and keyboard navigation
- Mobile-First: Designed to work perfectly on mobile devices from the start
- Documentation: Extensive documentation and community support
📚 Documentation & Resources
Bootstrap
📖 Bootstrap Documentation Official Bootstrap 5 documentation with examples and componentsTailwind CSS
📖 Tailwind Documentation Complete Tailwind CSS documentation with utility classesRecursive Functions
-
What is Recursion?
A function that calls itself. Must have a base case to avoid infinite loops. -
How They Work
Think of breaking a problem into smaller problems until it’s solvable (base case). -
Real-World Examples
- Fibonacci sequence
- Folder/file structure traversal
- Calculating factorials
- DOM tree manipulation
🧮 Live Example: Recursive Factorial
Enter a number to see how recursion works step by step. Open your browser's console (F12) to see the recursive process!
How it works: The function calls itself with a smaller number until it reaches the base case (0 or 1), then multiplies all the numbers together.
📝 The Recursive Function Code:
// Recursive function example: Calculate factorial
function factorial(n) {
console.log(`🔍 Calculating factorial(${n})...`);
// Base case: factorial of 0 or 1 is 1
if (n === 0 || n === 1) {
console.log(`✅ Base case reached! factorial(${n}) = 1`);
return 1;
}
// Recursive case: n! = n × (n-1)!
console.log(`🔄 Recursive case: ${n}! = ${n} × (${n-1})!`);
const result = n * factorial(n - 1);
console.log(`📊 factorial(${n}) = ${n} × ${result/n} = ${result}`);
return result;
}
🔑 Key Concepts:
- Base Case: The stopping condition (n === 0 or 1)
- Recursive Case: The function calls itself with a smaller value
- Call Stack: Each recursive call adds to the stack
- Return Values: Results bubble back up through the stack
📊 Example: factorial(3)
- factorial(3) calls factorial(2)
- factorial(2) calls factorial(1)
- factorial(1) returns 1 (base case)
- factorial(2) returns 2 × 1 = 2
- factorial(3) returns 3 × 2 = 6