React Lesson 7: useEffect Hook
useEffect lets you run code in response to events like component mounting, state changes, or cleanup. It’s how React components interact with the outside world (APIs, timers, etc.).
useEffect Basics
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
// Runs after EVERY render (no dependency array)
useEffect(() => {
document.title = `Count: ${count}`;
});
// Runs ONCE on mount (empty dependency array)
useEffect(() => {
console.log("Component mounted!");
}, []);
// Runs when count changes
useEffect(() => {
console.log("Count changed to:", count);
}, [count]); // dependency array
return <button onClick={() => setCount(count + 1)}>+</button>;
}
Fetching Data
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchUsers() {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const data = await res.json();
setUsers(data);
} catch (err) {
setError("Failed to load users");
} finally {
setLoading(false);
}
}
fetchUsers();
}, []); // [] means fetch once on mount
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
Cleanup Function
useEffect(() => {
const timer = setInterval(() => {
setTime(new Date());
}, 1000);
// Cleanup: runs before next effect or when component unmounts
return () => clearInterval(timer);
}, []);
🏋️ Practice Task
Build a live clock that shows the current time (hours:minutes:seconds) and updates every second. Use useState for the time and useEffect with setInterval. Make sure to clean up the interval when the component unmounts.
💡 Hint: const [time, setTime] = useState(new Date()). In useEffect: const timer = setInterval(() => setTime(new Date()), 1000). Return () => clearInterval(timer).