10. API Integration – Random Quote
Fetching external data using useEffect and fetch API.
RandomQuote Component
RandomQuote.js
import React, { useState, useEffect } from 'react'; // Line 1: Import hooks
function RandomQuote() { // Line 2: Component function
const [quote, setQuote] = useState(''); // Line 3: State for quote text
const [author, setAuthor] = useState(''); // Line 4: State for author
const [loading, setLoading] = useState(true); // Line 5: Loading state
const fetchQuote = async () => { // Line 6: Async fetch function
setLoading(true); // Line 7: Show loading
try { // Line 8: Error handling
const response = await fetch('https://api.quotable.io/random'); // Line 9: API call
const data = await response.json(); // Line 10: Parse JSON
setQuote(data.content); // Line 11: Set quote
setAuthor(data.author); // Line 12: Set author
} catch (error) { // Line 13: Catch errors
console.error('Error:', error); // Line 14: Log error
} // Line 15: Close try-catch
setLoading(false); // Line 16: Hide loading
}; // Line 17: Close function
useEffect(() => { fetchQuote(); }, []); // Line 18: Fetch on component mount
return ( // Line 19: Return JSX
<div className="quote-app"> // Line 20: Container
<h2>Random Quote Generator</h2> // Line 21: Title
{loading ? ( // Line 22: Loading condition
<p>Loading...</p> // Line 23: Loading text
) : ( // Line 24: Quote display
<div> // Line 25: Quote container
<blockquote>"{quote}"</blockquote> // Line 26: Quote text
<p>— {author}</p> // Line 27: Author
</div> // Line 28: Close container
)} // Line 29: Close condition
<button onClick={fetchQuote}>New Quote</button> // Line 30: Refresh button
</div> // Line 31: Close main div
); // Line 32: Close return
} // Line 33: Close function
export default RandomQuote; // Line 34: Export
Key API Concepts:
useEffectfor API calls on mountasync/awaitfor handling promises- Loading states for better UX
- Error handling with try-catch
Small Task: Add error state to display “Failed to load quote” when API fails. (Max 5 lines)
React.js Examples – Forms & Todo List
1. Login Form – Form Validation & State Management
LoginForm.js
import React, { useState } from 'react';
function LoginForm() {
const [form, setForm] = useState({ username: '', password: '' });
const [message, setMessage] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!form.username || !form.password) return setMessage('All fields required!');
form.username === 'admin' && form.password === 'password'
? setMessage('Login successful!') : setMessage('Invalid credentials!');
};
return (
<form onSubmit={handleSubmit}>
<input placeholder="Username" value={form.username}
onChange={(e) => setForm({...form, username: e.target.value})} />
<input type="password" placeholder="Password" value={form.password}
onChange={(e) => setForm({...form, password: e.target.value})} />
<button type="submit">Login</button>
{message && <p style={{color: message.includes('successful') ? 'green' : 'red'}}>{message}</p>}
</form>
);
}
export default LoginForm;
2. Todo List – Array State Management
TodoList.js
import React, { useState } from 'react';
function TodoList() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const addTodo = (e) => {
e.preventDefault();
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input, completed: false }]);
setInput('');
}
};
return (
<div>
<form onSubmit={addTodo}>
<input value={input} onChange={(e) => setInput(e.target.value)} placeholder="Add task" />
<button type="submit">Add</button>
</form>
{todos.map(todo => (
<div key={todo.id}>
<input type="checkbox" onChange={() => setTodos(todos.map(t => t.id === todo.id ? {...t, completed: !t.completed} : t))} />
<span style={{textDecoration: todo.completed ? 'line-through' : 'none'}}>{todo.text}</span>
</div>
))}
</div>
);
}
export default TodoList;
Key Concepts:
- Controlled components with
valueandonChange - Form submission with
e.preventDefault() - Array state updates with spread operator
- Conditional styling based on state


