Side Effects (Intro) 🌐
Components should stay pure, but real apps must sync with the outside world. useEffect is how React handles that work.
1) What Counts as a Side Effect? 🧠
- Fetching or mutating data outside React (APIs, localStorage).
- Subscribing to services (WebSocket, events, timers).
- Manipulating DOM nodes directly or integrating third-party widgets.
⚠️ Keep rendering pure; move imperative work into effects.
2) useEffect Basics ⚛️
useEffect runs after the render paints.
import { useEffect, useState } from "react";
function Greeting() {
const [message, setMessage] = useState("...");
useEffect(() => {
setMessage("Hello from useEffect!");
}, []);
return <p>{message}</p>;
}- First argument is a callback.
- Second argument (dependency array) controls when it runs.
3) Dependency Arrays 🧱
[]: run once on mount.[value]: run on mount and whenevervaluechanges.- Omit dependency array to run after every render (rarely needed).
React’s ESLint plugin warns when dependencies are missing—always include everything the effect reads.
4) Cleanup Functions 🧹
Return a function to clean up subscriptions, timers, or listeners.
function Clock() {
const [time, setTime] = useState(() => new Date().toLocaleTimeString());
useEffect(() => {
const id = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => clearInterval(id); // cleanup
}, []);
return <p>🕒 {time}</p>;
}- Cleanup runs before unmount and before the next effect reruns.
- Prevents memory leaks and duplicate subscriptions.
5) Common Patterns 🔄
Fetch on Mount
function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
let cancelled = false;
fetch("/api/posts")
.then(res => res.json())
.then(data => {
if (!cancelled) setPosts(data);
});
return () => {
cancelled = true;
};
}, []);
return <PostList posts={posts} />;
}Sync with Local Storage
function ThemeToggle() {
const [theme, setTheme] = useState(() => localStorage.getItem("theme") ?? "light");
useEffect(() => {
localStorage.setItem("theme", theme);
}, [theme]);
return (
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Theme: {theme}
</button>
);
}Key Takeaways ✅
- Effects handle work that cannot happen during rendering (I/O, subscriptions, DOM tweaks).
- Dependency arrays tell React when the effect should run again.
- Cleanup functions keep subscriptions tidy and prevent leaks.
- Pair
useEffectwithuseStateto synchronize React with external systems.
Recap 🔄
useEffect runs after React paints, enabling data fetching, subscriptions, and DOM integration. Supply the correct dependency array, clean up when necessary, and keep rendering pure by isolating side effects in these hooks.
Last updated on