Explain the useEffect Hook
Answer
useEffect schedules side effects after React commits DOM updates. Typical uses include fetching data, subscribing to events or stores, and synchronizing with non-React code.
- No dependency array — runs after every render.
[]— runs after mount (and cleanup before unmount). In Strict Mode (dev), effects may run twice to surface unsafe side effects.[deps]— runs when dependencies change; cleanup runs before re-running the effect.
Code Examples
jsx
import { useEffect, useState } from 'react'
export function UserProfile({ userId }) {
const [user, setUser] = useState(null)
useEffect(() => {
let cancelled = false
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => {
if (!cancelled) setUser(data)
})
return () => {
cancelled = true
}
}, [userId])
return user ? <p>{user.name}</p> : null
}jsx
useEffect(() => {
const id = setInterval(tick, 1000)
return () => clearInterval(id)
}, [tick])Common Mistakes
- Missing dependencies (stale closures) or over-including objects that change every render (infinite loops).
- Using
useEffectfor derived state instead of computing during render. - Omitting cleanup for subscriptions, timers, or pending fetches.
Follow-up Questions
- Difference between
useEffectanduseLayoutEffect? - How do you cancel async work on unmount?
- When would you use an event handler instead of an effect?
Real Interview Scenarios
Interviewers often present a component with an infinite re-render loop or a memory leak from a missing cleanup and ask you to fix it live.