useEffect Hook
Overview
React Components are essentially mathematical functions: data (props/state) goes in, and UI (JSX) comes out. This rendering calculation must be Pure, meaning it should never interact with the outside world during the calculation phase.
However, real applications must interact with the outside world. You need to fetch data from a server, start a timer, manually alter the DOM (like focusing an input), or subscribe to a WebSocket. These actions are called Side Effects.
The useEffect Hook is React's designated escape hatch. It allows you to safely execute side effects after React has successfully painted the UI to the browser screen. This ensures that slow side effects (like a 3-second API call) do not block the browser from immediately displaying the UI to the user.
Syntax
import { useState, useEffect } from 'react';
function DocumentTitle() {
const [count, setCount] = useState(0);
// 1. React renders the UI first (returns the JSX)
// 2. The browser paints the screen
// 3. React executes this useEffect block
useEffect(() => {
// A Side Effect: Manipulating the browser's Document API
document.title = `You clicked ${count} times`;
}); // Notice the missing array here! (We will cover this next)
return <button onClick={() => setCount(count + 1)}>Click Me</button>;
}Common Pitfalls
- Putting Side Effects in the Main Body: NEVER run an API fetch or manipulate the DOM directly inside the main body of your component. React will execute that code every single time the component re-renders (which can happen dozens of times per second). This leads to infinite loops and crashes.
Interview Questions
A pure function always returns the exact same output for the same input and produces no side effects. React requires the render phase to be pure so it can safely pause, abort, or restart renders (especially with React 18's Concurrent Mode) without accidentally mutating data on the server or in the browser DOM.
The callback function inside useEffect runs asynchronously after the render is committed to the screen. This guarantees that your side effect does not block the browser from painting the visual UI for the user.
Real-World Example
Focusing an Input on Load: Autofocusing an input requires direct manipulation of the DOM. You cannot do this while React is calculating the Virtual DOM; it must happen in a useEffect after the real input element actually exists on the screen.
function SearchBar() {
const inputRef = useRef(null);
// We want the cursor to automatically focus in the search bar when the page loads
useEffect(() => {
// This is a side effect because we are manually touching the DOM API
inputRef.current.focus();
}, []);
return <input ref={inputRef} placeholder="Search..." />;
}Check Your Knowledge
Test your understanding of useEffect Hook with these quick questions.