stackademic

The leading education platform for anyone with an interest in software development.

React useEffect

Run side effects after render: fetching data, subscriptions, and DOM sync

Overview

useEffect runs after React paints the screen. Use it for side effects that should not run during render—API calls, timers, event listeners, and syncing with non-React libraries. The cleanup function runs before the next effect and on unmount.

Syntax / Usage

import { useEffect, useState } from 'react'

function UserProfile({ userId }) {
  const [user, setUser] = useState(null)

  // Run when userId changes
  useEffect(() => {
    let cancelled = false

    async function load() {
      const res = await fetch(`/api/users/${userId}`)
      const data = await res.json()
      if (!cancelled) setUser(data)
    }

    load()
    return () => { cancelled = true }
  }, [userId])

  // Run once on mount
  useEffect(() => {
    document.title = 'My App'
  }, [])

  return user ? <p>{user.name}</p> : <p>Loading...</p>
}

Examples

Subscribe to window resize:

useEffect(() => {
  const onResize = () => setWidth(window.innerWidth)
  window.addEventListener('resize', onResize)
  return () => window.removeEventListener('resize', onResize)
}, [])

Debounce a search query:

useEffect(() => {
  const id = setTimeout(() => fetchResults(query), 300)
  return () => clearTimeout(id)
}, [query])

Common Mistakes

  • Missing dependencies causing stale closures—enable ESLint exhaustive-deps
  • Fetching in useEffect without abort/cancel on unmount or id change
  • Using useEffect for derived state—compute during render instead
  • Infinite loops from setting state in an effect without proper dependencies

See Also

use-state use-ref use-callback components