FrontendPrep
Menu
Topics
Questions
Guides
Challenges
Soon
Back to React Questions
reactHard

React useEffect Interview Questions

Master React useEffect interview questions with practical examples. Learn side effects, dependency arrays, cleanup functions, lifecycle behavior, common mistakes, and performance best practices.

React useEffect Interview Questions

One of the most frequently asked React interview questions is:

What is useEffect and why do we need it?

Most developers answer:

useEffect is used for API calls.

While API calls are a common use case, interviewers often go deeper:

  • What is a side effect?
  • When does useEffect run?
  • How does the dependency array work?
  • What are cleanup functions?
  • Can useEffect cause infinite loops?
  • What is the difference between useEffect and useLayoutEffect?

Let's understand useEffect from first principles.

1. Why Do We Need useEffect?

React components should primarily focus on:

Rendering UI

Example:

function UserCard() {
  return <h1>John</h1>;
}

However, applications often need to perform operations such as:

  • API requests
  • Event listeners
  • Timers
  • Analytics tracking
  • WebSocket connections
  • DOM interactions

These operations are called:

Side Effects

2. What is a Side Effect?

A side effect is any operation that interacts with something outside React's rendering process.

Examples:

fetch("/users");
setInterval(...);
window.addEventListener(...);
localStorage.setItem(...);

All of these are side effects.

3. Understanding the useEffect Hook

useEffect is a React Hook that allows components to perform side effects after rendering.

Example:

useEffect(() => {
  console.log("Effect");
});

React executes the effect after rendering is complete.

Visual Representation

Render

Paint

useEffect Runs

This sequence is important for interviews.

Basic Example

function App() {
  useEffect(() => {
    console.log("Mounted");
  });
 
  return <h1>Hello</h1>;
}

Output:

Mounted

after rendering occurs.

How useEffect Works

Syntax:

useEffect(() => {
  // Side Effect
});

Structure:

useEffect(effectFunction, dependencies);

4. Controlling Execution: The Dependency Array

The dependency array controls when the effect runs.

Example:

useEffect(() => {
  console.log("Effect");
}, []);

Understanding dependency arrays is one of the most important React interview topics.

Case 1: No Dependency Array

Example:

useEffect(() => {
  console.log("Effect");
});

Runs:

Every Render

Example

function Counter() {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    console.log("Effect");
  });
 
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Every click:

Render

Effect Runs

Case 2: Empty Dependency Array

Example:

useEffect(() => {
  console.log("Mounted");
}, []);

Runs:

Only Once
After Initial Mount

Common Use Cases

Perfect for:

  • Initial API requests
  • Analytics initialization
  • Event listener setup
  • WebSocket connections

API Call Example

useEffect(() => {
  fetchUsers();
}, []);

Runs only once when the component mounts.

Case 3: Specific Dependencies

Example:

useEffect(() => {
  console.log("Count Changed");
}, [count]);

Runs whenever:

count;

changes.

Visual Representation

count Changes

Re-render

Effect Runs

Multiple Dependencies

Example:

useEffect(() => {
  console.log("Updated");
}, [count, user]);

Runs when:

count;

or

user;

changes.

5. Resource Management: Cleanup Functions

One of the most important useEffect concepts.

Example:

useEffect(() => {
  console.log("Effect");
 
  return () => {
    console.log("Cleanup");
  };
}, []);

What is a Cleanup Function?

A cleanup function allows React to remove resources created by an effect.

Common examples:

  • Timers
  • Event listeners
  • Subscriptions
  • WebSocket connections

Timer Example

Bad:

useEffect(() => {
  setInterval(() => {
    console.log("Running");
  }, 1000);
}, []);

Problem:

Interval Never Stops

Correct

useEffect(() => {
  const id = setInterval(() => {
    console.log("Running");
  }, 1000);
 
  return () => {
    clearInterval(id);
  };
}, []);

Event Listener Example

Bad:

useEffect(() => {
  window.addEventListener("resize", handleResize);
}, []);

Problem

Listener Remains
After Component Removal

Correct

useEffect(() => {
  window.addEventListener("resize", handleResize);
 
  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, []);

When Does Cleanup Run?

Interviewers frequently ask this.

Cleanup runs:

Before Unmount

Component Removed

Before The Next Effect

Example:

useEffect(() => {
  console.log("Effect");
 
  return () => {
    console.log("Cleanup");
  };
}, [count]);

When:

count;

changes:

Output:

Cleanup
Effect

6. Common Pitfall: Infinite Loops

A common interview question.

Bad:

const [count, setCount] = useState(0);
 
useEffect(() => {
  setCount(count + 1);
});

Result:

Render

Effect

State Update

Render

Effect

Infinite loop.

Why Does This Happen?

Because:

State Update

Re-render

Effect Runs Again

repeats forever.

Fix

Example:

useEffect(() => {
  setCount(1);
}, []);

Runs only once.

7. Common Pitfall: Stale Closures & Missing Dependencies

Example:

useEffect(() => {
  console.log(user);
}, []);

Problem:

user;

is used but not included.

Potential issue:

Stale Data

Correct

useEffect(() => {
  console.log(user);
}, [user]);

Stale Closure Example

A common senior-level topic.

Example:

useEffect(() => {
  const id = setInterval(() => {
    console.log(count);
  }, 1000);
 
  return () => clearInterval(id);
}, []);

Problem:

count Never Updates

inside the interval.

Why?

The effect captures:

count;

from the initial render.

This is called:

Stale Closure

8. Production Pattern: Fetch Requests & AbortController

useEffect(() => {
  fetch("/users")
    .then((res) => res.json())
    .then(setUsers);
}, []);

Very common production usage.

AbortController Pattern

Better:

useEffect(() => {
  const controller = new AbortController();
 
  fetch("/users", {
    signal: controller.signal,
  });
 
  return () => {
    controller.abort();
  };
}, []);

Prevents unnecessary requests after unmounting.

9. useEffect vs. useLayoutEffect

A common senior interview topic.

useEffect

Runs:

After Paint

useLayoutEffect

Runs:

Before Paint

and blocks rendering.

Visual Representation

useEffect

Render

Paint

Effect

useLayoutEffect

Render

Layout Effect

Paint

10. React 18 Strict Mode Effect Behavior

In development:

<React.StrictMode>

may execute effects twice.

Example:

useEffect(() => {
  console.log("Mounted");
}, []);

Development:

Mounted
Mounted

Production:

Mounted

11. Common Interview Q&A

What is useEffect?

A hook for performing side effects after rendering.

What Are Side Effects?

Operations that interact with systems outside React rendering.

Examples:

  • API calls
  • Timers
  • Event listeners

When Does useEffect Run?

After React completes rendering and painting.

What Does an Empty Dependency Array Mean?

Run Once After Mount

What Happens Without a Dependency Array?

Runs After Every Render

When Does Cleanup Run?

  • Before unmount
  • Before the next effect executes

What Causes Infinite Loops in useEffect?

State updates that continuously trigger re-renders.

What Is a Stale Closure?

An effect capturing outdated values from previous renders.

Dependency Array Summary

Dependency ArrayBehavior
No ArrayEvery Render
[]Initial Mount Only
[count]When count Changes
[count, user]When Any Dependency Changes

Senior-Level Interview Answer

useEffect is a React Hook used for performing side effects after rendering. Common side effects include API requests, timers, subscriptions, event listeners, and browser storage interactions. The dependency array determines when the effect executes. An empty dependency array causes the effect to run only after the initial mount, while specified dependencies cause re-execution when those values change. Effects can also return cleanup functions that run before unmounting or before subsequent effect executions, helping prevent memory leaks and stale subscriptions. Understanding dependency management, cleanup behavior, and stale closures is essential for building reliable React applications.

Common Interview Mistakes

❌ useEffect Is Only For API Calls

Correct:

useEffect handles all kinds
of side effects.

❌ Cleanup Runs Only On Unmount

Correct:

Cleanup also runs before
the next effect executes.

❌ Empty Dependency Arrays Are Always Correct

Correct:

Dependencies should reflect
values used inside the effect.

❌ useEffect Runs Before Render

Correct:

Render Happens First.
 
Effect Runs After Paint.

Key Takeaways

  • Side Effects: Operations that interact with the outside world (APIs, timers, storage) outside the render pipeline.
  • Rendering Sequence: Effects run asynchronously after the render is committed and painted to the screen.
  • Dependency Array: Controls execution; empty [] runs once, populated [deps] runs on changes, omitted runs on every render.
  • Cleanup Return: Executes before the component unmounts and before the next effect run, preventing memory leaks.
  • Stale Closures: Occur when dependencies are missing, capturing variables from older render scopes.

Share this Resource

Help other developers level up by sharing this study guide.

More Technical Questions

Expand your mastery. Deep dive into other frontend interview challenges in this category.