Skip to main content

📘 React Component Lifecycle — Complete Theory Guide


1. 🧠 Introduction

🔹 What is Component Lifecycle?

The Component Lifecycle in React refers to the series of phases a component goes through from:
Creation → Updating → Removal (Unmounting)
Each phase provides specific methods (class components) or hooks (functional components) that allow you to control behavior at different stages.

🔹 Why is it Important?

Understanding lifecycle is critical because it allows you to:
  • Control when side effects run
  • Manage API calls & subscriptions
  • Optimize performance
  • Prevent memory leaks
  • Handle DOM interactions safely

🔹 When & Why Do We Use It?

You use lifecycle logic when:
  • Fetching data from APIs
  • Setting up event listeners
  • Working with timers (setInterval / setTimeout)
  • Updating DOM manually
  • Cleaning up resources (subscriptions, listeners)

2. ⚙️ Concepts / Internal Workings


🔹 Lifecycle Phases

React lifecycle is divided into 3 main phases:

1️⃣ Mounting Phase (Component Creation)

When a component is created and inserted into the DOM. Class Methods:
  • constructor()
  • render()
  • componentDidMount()
Functional Equivalent:
  • useEffect(() => {}, [])

2️⃣ Updating Phase (Re-rendering)

Occurs when:
  • Props change
  • State changes
  • Parent re-renders
Class Methods:
  • shouldComponentUpdate()
  • render()
  • componentDidUpdate()
Functional Equivalent:
  • useEffect(() => {}, [dependencies])

3️⃣ Unmounting Phase (Component Removal)

When a component is removed from the DOM. Class Method:
  • componentWillUnmount()
Functional Equivalent:
  • Cleanup function in useEffect

🔹 Internal Working in React

React lifecycle is tightly coupled with:

⚡ Reconciliation Algorithm

  • React compares previous and next Virtual DOM
  • Determines minimal updates
  • Triggers lifecycle accordingly

⚡ Render vs Commit Phase

React internally splits work into:

🧩 Render Phase (Pure Calculation)

  • Calculates what should change
  • Can be paused or restarted

🧩 Commit Phase (DOM Update)

  • Applies changes to DOM
  • Runs lifecycle methods like:
    • componentDidMount
    • componentDidUpdate
    • useEffect

🔹 Relationship with Other React Features

✔️ State

  • State updates trigger lifecycle (re-renders)

✔️ Props

  • Prop changes cause update phase

✔️ Hooks

  • Replace lifecycle methods in functional components

✔️ Strict Mode

  • May run lifecycle twice (dev only) to detect bugs

3. 💻 Syntax & Examples


🔹 Class Component Lifecycle Example

import React from "react";

class LifecycleDemo extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    console.log("Constructor");
  }

  componentDidMount() {
    console.log("Component Mounted");
  }

  componentDidUpdate(prevProps, prevState) {
    console.log("Component Updated");
  }

  componentWillUnmount() {
    console.log("Component Unmounted");
  }

  render() {
    console.log("Render");
    return (
      <div>
        <h2>{this.state.count}</h2>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Increment
        </button>
      </div>
    );
  }
}

export default LifecycleDemo;

🔹 Functional Component (Modern Approach)

import { useEffect, useState } from "react";

function LifecycleDemo() {
  const [count, setCount] = useState(0);

  // Mounting
  useEffect(() => {
    console.log("Mounted");

    return () => {
      console.log("Unmounted");
    };
  }, []);

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

  return (
    <div>
      <h2>{count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

🔹 API Call Example (Real-world)

import { useEffect, useState } from "react";

function Users() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(res => res.json())
      .then(data => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

🔹 Cleanup Example (Important)

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

  return () => {
    clearInterval(interval);
    console.log("Cleaned up");
  };
}, []);

🔹 Conditional Effect Example

useEffect(() => {
  if (count > 5) {
    console.log("Count is greater than 5");
  }
}, [count]);

4. ⚠️ Edge Cases / Common Mistakes


❌ Infinite Loops in useEffect

useEffect(() => {
  setCount(count + 1); // ❌ Causes infinite loop
}, [count]);
Fix:
  • Use conditions or proper dependencies

❌ Missing Dependency Array

useEffect(() => {
  console.log("Runs on every render"); // Might be unintended
});

❌ Incorrect Cleanup

useEffect(() => {
  window.addEventListener("resize", handleResize);
}, []);
👉 Missing cleanup → Memory leak Fix:
return () => window.removeEventListener("resize", handleResize);

❌ Using componentDidMount Logic Incorrectly

  • In hooks, forgetting [] leads to repeated execution

❌ State Updates in Render (Class)

render() {
  this.setState({ count: 1 }); // ❌ Crash / infinite loop
}

❌ Stale Closures

useEffect(() => {
  setInterval(() => {
    console.log(count); // ❌ Old value
  }, 1000);
}, []);
Fix:
  • Use refs or include dependency

❌ Strict Mode Double Execution

  • useEffect may run twice in development
  • This is intentional for detecting side effects

5. ✅ Best Practices


🔹 1. Prefer Functional Components + Hooks

  • Hooks are more readable and composable
  • Avoid legacy lifecycle unless maintaining old code

🔹 2. Keep Effects Focused

👉 One effect = one responsibility
// ❌ Bad
useEffect(() => {
  fetchData();
  document.title = "App";
}, []);

// ✅ Good
useEffect(fetchData, []);
useEffect(() => {
  document.title = "App";
}, []);

🔹 3. Always Handle Cleanup

  • Timers
  • Event listeners
  • Subscriptions

🔹 4. Optimize Re-renders

  • Use:
    • React.memo
    • useMemo
    • useCallback

🔹 5. Avoid Unnecessary Effects

👉 If you can compute something during render, don’t use useEffect

🔹 6. Use Dependency Array Carefully

  • Include all dependencies
  • Follow ESLint rule: react-hooks/exhaustive-deps

🔹 7. Avoid Heavy Work in Effects

  • Offload heavy tasks
  • Use debouncing / throttling

🔹 8. Handle Async Safely

useEffect(() => {
  let isMounted = true;

  fetchData().then(data => {
    if (isMounted) setData(data);
  });

  return () => {
    isMounted = false;
  };
}, []);

🔹 9. Think in Terms of Synchronization

React lifecycle is not about “steps” — it’s about:
Syncing UI with state & external systems

🔹 10. Understand Timing

Hook / MethodWhen it runs
renderBefore DOM update
useEffectAfter DOM update
useLayoutEffectBefore browser paint

🔚 Final Summary

  • Lifecycle = Mount → Update → Unmount
  • Hooks replace class lifecycle methods
  • useEffect is the core tool for lifecycle management
  • Correct dependency management is critical
  • Cleanup prevents memory leaks
  • Think in terms of data flow & synchronization, not just lifecycle steps

🧠 React Component Lifecycle — Senior-Level Interview Questions


1. What is the real purpose of the component lifecycle in modern React, beyond the basic definition?

✅ Strong Answer

At a senior level, lifecycle is not about “mount/update/unmount” — it’s about:
Synchronizing UI with external systems and side effects
React is declarative, but:
  • APIs
  • DOM APIs
  • subscriptions
  • timers
…are imperative systems Lifecycle provides controlled points to:
  • start synchronization (mount / dependency change)
  • update synchronization (state/prop changes)
  • stop synchronization (cleanup)
👉 Example:
useEffect(() => {
  const socket = connect();

  return () => socket.disconnect();
}, []);

💡 Why this matters

  • Prevents memory leaks
  • Avoids race conditions
  • Ensures UI consistency

⚖️ Trade-off

  • Overusing lifecycle → unnecessary complexity
  • Underusing → bugs and leaks

2. How does React internally decide when to trigger lifecycle methods or hooks?

✅ Strong Answer

Lifecycle is driven by React’s reconciliation process:
  1. React builds a new Virtual DOM
  2. Compares it with the previous one (diffing)
  3. Determines minimal changes
  4. During commit phase:
    • Runs lifecycle methods / effects

🔍 Key Insight

React has two phases:
PhaseDescription
RenderPure calculation (can be interrupted)
CommitApplies DOM changes + runs effects
👉 useEffect runs after commit

⚠️ Why it matters

  • Effects should not rely on render timing
  • DOM is guaranteed to be updated when useEffect runs

3. Why does useEffect run after render instead of before?

✅ Strong Answer

Because React prioritizes UI consistency and non-blocking rendering If effects ran before:
  • They could block rendering
  • UI would feel slow
Instead:
  • React renders UI first
  • Then runs effects asynchronously

🔁 Comparison

HookTiming
useEffectAfter paint
useLayoutEffectBefore paint

💡 Example

useEffect(() => {
  console.log("Runs after UI updates");
});

⚖️ Trade-off

  • useEffect: better performance
  • useLayoutEffect: needed for DOM measurement but can block rendering

4. Why does React Strict Mode intentionally double-invoke lifecycle logic?

✅ Strong Answer

In development, React Strict Mode intentionally:
  • Mounts → unmounts → mounts again
This exposes:
  • Side effects that aren’t idempotent
  • Missing cleanup logic

💡 Example Problem

useEffect(() => {
  fetchData(); // runs twice in dev
}, []);

🔍 Why this exists

React prepares for:
  • Concurrent rendering
  • Interruptible rendering

⚖️ Trade-off

  • Confusing for beginners
  • Extremely valuable for catching bugs early

5. What are the risks of treating useEffect as a replacement for all lifecycle logic?

✅ Strong Answer

Common misconception:
“Put everything in useEffect”

❌ Problems

  1. Overuse
    • Leads to unnecessary re-renders
  2. Derived state misuse
useEffect(() => {
  setFiltered(list.filter(...)); // ❌ unnecessary
}, [list]);
👉 Should compute during render instead
  1. Tight coupling of logic

✅ Better Approach

  • Use effects only for:
    • External systems
    • Side effects

💡 Principle

“If it can be calculated during render, don’t use useEffect.”

6. Explain the concept of stale closures in lifecycle logic.

✅ Strong Answer

Closures capture values at the time of render, not live values.

❌ Problem

useEffect(() => {
  setInterval(() => {
    console.log(count); // stale value
  }, 1000);
}, []);

🔍 Why it happens

  • Effect runs once
  • Closure captures initial count

✅ Solutions

1. Add dependency

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

  return () => clearInterval(id);
}, [count]);

2. Use ref


⚖️ Trade-off

  • Adding dependencies → more re-renders
  • Using refs → more manual control

7. Why is cleanup in lifecycle critical, and what happens if you skip it?

✅ Strong Answer

Cleanup prevents:
  • Memory leaks
  • Duplicate subscriptions
  • Unexpected behavior

❌ Example

useEffect(() => {
  window.addEventListener("resize", handleResize);
}, []);
👉 On remount → multiple listeners

✅ Correct

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

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

💡 Real-world Impact

  • Performance degradation
  • Hard-to-debug bugs

8. How does dependency array affect lifecycle behavior internally?

✅ Strong Answer

Dependency array controls when React re-runs the effect. React:
  • Compares previous dependencies with new ones (shallow comparison)
  • If changed → runs cleanup → runs effect again

🔍 Example

useEffect(() => {
  console.log("Runs when count changes");
}, [count]);

⚠️ Pitfall

Objects/functions always change reference:
useEffect(() => {}, [{}]); // runs every time

✅ Solution

  • useMemo
  • useCallback

9. What is the difference between useEffect and useLayoutEffect in real-world scenarios?

✅ Strong Answer

FeatureuseEffectuseLayoutEffect
TimingAfter paintBefore paint
BlockingNoYes

💡 Use Cases

useEffect

  • API calls
  • Logging
  • subscriptions

useLayoutEffect

  • Measuring DOM
  • Sync layout changes

⚠️ Example

useLayoutEffect(() => {
  const height = ref.current.offsetHeight;
});

⚖️ Trade-off

  • useLayoutEffect can hurt performance
  • Should be used sparingly

10. How does React handle lifecycle during re-renders caused by parent components?

✅ Strong Answer

When parent re-renders:
  • Child components also re-render by default
Even if props didn’t change

🔍 Why?

React does not automatically memoize components

✅ Optimization

export default React.memo(Component);

⚖️ Trade-off

  • Memoization adds complexity
  • Useful only when render is expensive

11. Why is it dangerous to update state unconditionally inside lifecycle logic?

✅ Strong Answer

It causes infinite render loops

❌ Example

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

🔍 Why?

  • State update → re-render → effect runs → repeat

✅ Fix

  • Add condition
  • Use functional updates

12. Explain how async operations interact with lifecycle and potential issues.

✅ Strong Answer

Async operations can complete:
  • After component unmount
  • In different order (race conditions)

❌ Problem

useEffect(() => {
  fetchData().then(setData);
}, []);

⚠️ Issues

  • Setting state on unmounted component
  • Data inconsistency

✅ Solution

useEffect(() => {
  let isMounted = true;

  fetchData().then(data => {
    if (isMounted) setData(data);
  });

  return () => {
    isMounted = false;
  };
}, []);

13. What design trade-offs led React to move from class lifecycle methods to hooks?

✅ Strong Answer

❌ Problems with class lifecycle

  • Logic scattered across methods
  • Hard to reuse logic
  • Complex mental model

✅ Hooks solve:

  • Co-locating logic
  • Reusability (custom hooks)
  • Simpler composition

💡 Example

Before:
componentDidMount()
componentDidUpdate()
After:
useEffect(() => {
  // unified logic
});

⚖️ Trade-off

  • Hooks introduce dependency complexity
  • Learning curve for closures

14. How does React ensure consistency between UI and effects in concurrent rendering?

✅ Strong Answer

React ensures:
  • Effects only run after committed UI
Even if render is interrupted:
  • Effects from abandoned renders are discarded

🔍 Why important?

  • Prevents inconsistent state
  • Avoids running effects for UI that never appeared

15. When should you NOT use lifecycle logic at all?

✅ Strong Answer

Avoid lifecycle when:
  • Computing derived data
  • Formatting values
  • Filtering lists

❌ Bad

useEffect(() => {
  setFullName(first + last);
}, [first, last]);

✅ Good

const fullName = first + last;

💡 Principle

Lifecycle is for side effects, not data transformation

🔚 Final Takeaway

At a senior level:
  • Lifecycle is about synchronization, not steps
  • Effects must be:
    • intentional
    • minimal
    • predictable
  • Misusing lifecycle leads to:
    • performance issues
    • subtle bugs
    • hard-to-debug behavior

🧠 React Component Lifecycle — Advanced MCQs (Senior Level)


1. When does useEffect actually execute in React?

Question: Given a component render, when is useEffect guaranteed to run? A. Before render begins B. After render but before DOM updates C. After DOM updates are committed to the screen D. During reconciliation phase Correct Answer: C

✅ Explanation

  • useEffect runs after the commit phase, meaning:
    • DOM is updated
    • Browser has painted (usually)
👉 Ensures non-blocking UI updates.

❌ Why others are wrong

  • A: Effects never run before render
  • B: That’s useLayoutEffect
  • D: Reconciliation is pure calculation; effects don’t run there

2. What happens if you omit the dependency array in useEffect?

A. Runs only once on mount B. Runs on every render C. Runs only when state changes D. Runs only on unmount Correct Answer: B

✅ Explanation

Without dependencies, React assumes:
“Run after every render”

❌ Why others are wrong

  • A: Only happens with []
  • C: Not limited to state changes
  • D: Cleanup runs on unmount, not effect

3. What is the behavior of this code in Strict Mode (development)?

useEffect(() => {
  console.log("Mounted");
}, []);
A. Logs once B. Logs twice C. Logs infinitely D. Logs once in production, never in development Correct Answer: B

✅ Explanation

In React Strict Mode:
  • React mounts → unmounts → mounts again
  • Helps detect unsafe side effects

❌ Why others are wrong

  • A: True only in production
  • C: No loop here
  • D: Opposite of reality

4. What is the biggest issue with this code?

useEffect(() => {
  setCount(count + 1);
}, [count]);
A. No issue B. Memory leak C. Infinite re-render loop D. Stale closure Correct Answer: C

✅ Explanation

  • count changes → effect runs → updates state → repeat

❌ Why others are wrong

  • A: Definitely problematic
  • B: No leak here
  • D: Closure is fresh due to dependency

5. What happens if an object is used as a dependency?

useEffect(() => {}, [{ a: 1 }]);
A. Runs once B. Runs only if object changes deeply C. Runs on every render D. Throws error Correct Answer: C

✅ Explanation

  • React does shallow comparison
  • New object reference each render → effect runs

❌ Why others are wrong

  • A: Only for stable reference
  • B: No deep comparison
  • D: Valid code

6. Which scenario requires useLayoutEffect instead of useEffect?

A. Fetching API data B. Logging analytics C. Measuring DOM size before paint D. Setting timers Correct Answer: C

✅ Explanation

  • useLayoutEffect runs before paint
  • Needed for layout measurements to avoid flicker

❌ Why others are wrong

  • A/B/D: Non-blocking tasks → useEffect preferred

7. What happens if cleanup is missing in an effect with event listeners?

A. Nothing B. Event listeners stack up C. React auto-cleans them D. Component crashes immediately Correct Answer: B

✅ Explanation

  • Each mount adds a new listener
  • Leads to duplicate handlers

❌ Why others are wrong

  • A: Incorrect, causes bugs
  • C: React does not auto-clean external effects
  • D: No immediate crash

8. What is the key problem in this code?

useEffect(() => {
  setInterval(() => console.log(count), 1000);
}, []);
A. Infinite loop B. Stale closure C. Memory leak D. Both B and C Correct Answer: D

✅ Explanation

  • Stale closure → logs old count
  • Memory leak → interval never cleared

❌ Why others are wrong

  • A: No loop triggered
  • B/C: Both issues exist

9. What ensures effects from abandoned renders don’t execute?

A. Dependency array B. Cleanup function C. Commit phase control D. Memoization Correct Answer: C

✅ Explanation

  • React only runs effects for committed renders
  • Discards interrupted renders

❌ Why others are wrong

  • A/B/D: Not responsible for this guarantee

10. What happens when a parent re-renders but props don’t change?

A. Child never re-renders B. Child always re-renders C. Child re-renders only in Strict Mode D. Child re-renders only if state changes Correct Answer: B

✅ Explanation

  • React re-renders children by default

❌ Why others are wrong

  • A: Needs React.memo
  • C/D: Incorrect assumptions

11. Which is the correct cleanup timing?

A. Before next effect runs B. After component unmounts only C. Before render phase D. After every render Correct Answer: A

✅ Explanation

Cleanup runs:
  • Before next effect
  • On unmount

❌ Why others are wrong

  • B: Not only unmount
  • C/D: Incorrect timing

12. What is the issue with derived state in useEffect?

A. No issue B. Causes unnecessary re-renders C. Breaks React rules D. Causes memory leaks Correct Answer: B

✅ Explanation

Derived state:
  • Can be computed during render
  • Using effect → extra render cycle

❌ Why others are wrong

  • A: Suboptimal pattern
  • C: Not illegal
  • D: No leak

13. What is the behavior of useEffect with multiple dependencies?

A. Runs if all change B. Runs if any change C. Runs only on mount D. Runs randomly Correct Answer: B

✅ Explanation

  • Any dependency change triggers effect

❌ Why others are wrong

  • A: Not required for all
  • C/D: Incorrect

14. Why should heavy computations be avoided inside effects?

A. Effects run before render B. Blocks UI thread C. Causes memory leaks D. Prevents cleanup Correct Answer: B

✅ Explanation

  • JS is single-threaded
  • Heavy work blocks responsiveness

❌ Why others are wrong

  • A: Effects run after render
  • C/D: Not directly related

15. What happens if you forget dependencies in async effect?

A. Nothing B. Runs only once C. May use stale data D. Crashes app Correct Answer: C

✅ Explanation

  • Missing dependencies → stale values captured

❌ Why others are wrong

  • A/B/D: Misrepresent behavior

16. What is the correct pattern to prevent state updates after unmount?

A. Try/catch B. isMounted flag or AbortController C. setTimeout D. useMemo Correct Answer: B

✅ Explanation

Prevents:
  • Updating unmounted component
  • Race conditions

❌ Why others are wrong

  • A: Not relevant
  • C/D: No effect

17. Why does React discourage side effects during render?

A. Slows down browser B. Breaks purity of render C. Causes memory leaks D. Prevents updates Correct Answer: B

✅ Explanation

Render must be:
  • Pure
  • Predictable
  • Side-effect free

❌ Why others are wrong

  • A/C/D: Secondary or incorrect reasons

18. What is the impact of React.memo on lifecycle?

A. Skips lifecycle completely B. Skips re-render if props unchanged C. Prevents useEffect from running D. Disables state updates Correct Answer: B

✅ Explanation

  • Memo prevents unnecessary re-renders
  • Lifecycle tied to render → skipped if not re-rendered

❌ Why others are wrong

  • A: Lifecycle still exists
  • C/D: Incorrect behavior

🔚 Final Insight

These questions test whether a developer understands:
  • Lifecycle = synchronization model
  • Effects = controlled side effects
  • React = render → commit → effect
👉 Senior engineers:
  • Avoid misuse of lifecycle
  • Optimize effects
  • Understand internal timing deeply

🧠 React Component Lifecycle — Real-World Coding Problems (Senior Level)


1. Auto-Save Form with Debounce

🧩 Problem

Build a form that auto-saves user input after 500ms of inactivity.

⚙️ Constraints

  • Avoid API calls on every keystroke
  • Cancel previous pending save if user types again
  • Save only latest value

✅ Expected Behavior

  • User types → waits → API called once
  • Rapid typing → only last value saved

⚠️ Edge Cases

  • Component unmount before timeout
  • Rapid typing
  • Stale values

💡 Solution Approach

useEffect(() => {
  const timer = setTimeout(() => {
    saveData(input);
  }, 500);

  return () => clearTimeout(timer);
}, [input]);

🧠 Explanation

  • Cleanup cancels previous timer
  • Prevents multiple API calls
  • Uses lifecycle to sync input → API

2. Prevent State Update After Unmount (API Call)

🧩 Problem

Fetch data from API but prevent updating state if component unmounts.

⚙️ Constraints

  • Avoid memory leaks
  • Handle slow API

⚠️ Edge Cases

  • Component unmounts before response
  • Multiple requests

💡 Solution

useEffect(() => {
  let isMounted = true;

  fetchData().then(data => {
    if (isMounted) setData(data);
  });

  return () => {
    isMounted = false;
  };
}, []);

🧠 Explanation

  • Lifecycle cleanup prevents unsafe updates

3. Window Resize Listener

🧩 Problem

Track window width and update UI.

⚙️ Constraints

  • Add listener once
  • Remove on unmount

⚠️ Edge Cases

  • Multiple mounts
  • Memory leaks

💡 Solution

useEffect(() => {
  const handleResize = () => setWidth(window.innerWidth);

  window.addEventListener("resize", handleResize);

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

🧠 Explanation

  • Lifecycle manages subscription lifecycle

4. Polling API Every 5 Seconds

🧩 Problem

Fetch updated data every 5 seconds.

⚙️ Constraints

  • Stop polling on unmount
  • Avoid multiple intervals

💡 Solution

useEffect(() => {
  const id = setInterval(fetchData, 5000);

  return () => clearInterval(id);
}, []);

⚠️ Edge Cases

  • Interval stacking
  • Component unmount

5. Sync Document Title

🧩 Problem

Update document.title based on state.

💡 Solution

useEffect(() => {
  document.title = `Count: ${count}`;
}, [count]);

🧠 Insight

  • Side effect tied to state

6. Abort Fetch on Dependency Change

🧩 Problem

Cancel previous API request when search query changes.

💡 Solution

useEffect(() => {
  const controller = new AbortController();

  fetch(`/api?q=${query}`, { signal: controller.signal })
    .then(res => res.json())
    .then(setData);

  return () => controller.abort();
}, [query]);

⚠️ Edge Cases

  • Race conditions
  • Rapid query changes

7. Detect First Render Only

🧩 Problem

Run logic only on first render.

💡 Solution

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

⚠️ Twist

Avoid misusing for derived state

8. Track Previous State Value

🧩 Problem

Compare current and previous value of a variable.

💡 Solution

const prevRef = useRef();

useEffect(() => {
  prevRef.current = value;
}, [value]);

🧠 Insight

  • Lifecycle helps track changes over time

9. Prevent Infinite Loop in Effect

🧩 Problem

Fix an effect causing infinite re-renders.

💡 Solution

useEffect(() => {
  if (count < 10) {
    setCount(count + 1);
  }
}, [count]);

🧠 Insight

  • Add conditions to break loops

10. Lazy Load Component on Visibility

🧩 Problem

Load data only when component enters viewport.

💡 Solution

useEffect(() => {
  const observer = new IntersectionObserver(([entry]) => {
    if (entry.isIntersecting) fetchData();
  });

  observer.observe(ref.current);

  return () => observer.disconnect();
}, []);

⚠️ Edge Cases

  • Multiple triggers
  • Cleanup

11. Debounced Search with API Cancellation

🧩 Problem

Combine debounce + cancel previous request.

💡 Solution

  • Use both setTimeout + AbortController

🧠 Insight

  • Multiple lifecycle concerns combined

12. Sync LocalStorage with State

🧩 Problem

Persist state to localStorage.

💡 Solution

useEffect(() => {
  localStorage.setItem("data", JSON.stringify(data));
}, [data]);

⚠️ Edge Cases

  • Serialization errors
  • Large data

13. Custom Hook: useInterval

🧩 Problem

Create reusable interval hook.

💡 Solution

function useInterval(callback, delay) {
  useEffect(() => {
    const id = setInterval(callback, delay);
    return () => clearInterval(id);
  }, [callback, delay]);
}

🧠 Insight

  • Lifecycle abstraction

14. Avoid Stale Closure in Interval

🧩 Problem

Fix stale state inside interval.

💡 Solution

useEffect(() => {
  const id = setInterval(() => {
    setCount(c => c + 1);
  }, 1000);

  return () => clearInterval(id);
}, []);

🧠 Insight

  • Functional updates avoid stale closure

15. Conditional Effect Execution

🧩 Problem

Run effect only when a condition is met.

💡 Solution

useEffect(() => {
  if (!isLoggedIn) return;
  fetchData();
}, [isLoggedIn]);

🧠 Insight

  • Guard conditions inside effect

16. Multi-Effect Separation

🧩 Problem

Split unrelated logic into separate effects.

💡 Solution

useEffect(fetchUsers, []);
useEffect(updateTitle, [count]);

🧠 Insight

  • Improves maintainability

17. Handle Rapid Prop Changes

🧩 Problem

Prop changes quickly → avoid race conditions.

💡 Solution

  • Use AbortController or tracking ID

🧠 Insight

  • Lifecycle must handle async ordering

18. Animate on Mount

🧩 Problem

Trigger animation when component mounts.

💡 Solution

useEffect(() => {
  setAnimate(true);
}, []);

⚠️ Edge Case

  • Strict Mode double-trigger

19. Global Event Bus Subscription

🧩 Problem

Subscribe to external event system.

💡 Solution

useEffect(() => {
  bus.subscribe(handler);
  return () => bus.unsubscribe(handler);
}, []);

🧠 Insight

  • Lifecycle manages external systems

🔚 Final Thought

These problems test:
  • Lifecycle as synchronization
  • Managing side effects safely
  • Handling async + cleanup + performance

🧠 React Component Lifecycle — Debugging Challenges (Senior Code Review)


1. 🔥 Infinite Re-render Loop (Hidden)

useEffect(() => {
  setFilters({ active: true });
}, [filters]);

❌ What’s Wrong

  • State update depends on filters, but also updates it → loop

🤯 Why It Happens

  • New object reference each time → dependency always “changes”

✅ Fix

useEffect(() => {
  setFilters(prev => ({ ...prev, active: true }));
}, []);

💡 Best Practice

  • Avoid setting state from itself inside dependency-based effects
  • Use functional updates or rethink logic

2. 🧨 Stale Closure in Interval

useEffect(() => {
  const id = setInterval(() => {
    setCount(count + 1);
  }, 1000);
}, []);

❌ What’s Wrong

  • count is always initial value

🤯 Why

  • Closure captures value at mount

✅ Fix

useEffect(() => {
  const id = setInterval(() => {
    setCount(c => c + 1);
  }, 1000);

  return () => clearInterval(id);
}, []);

💡 Best Practice

  • Use functional updates for async loops

3. ⚠️ Memory Leak with Event Listener

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

❌ What’s Wrong

  • No cleanup → multiple listeners over time

🤯 Why

  • Component unmount/remount adds new listener each time

✅ Fix

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

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

💡 Best Practice

  • Always clean up subscriptions

4. 🐛 Incorrect Dependency (Silent Bug)

useEffect(() => {
  fetchUser(userId);
}, []);

❌ What’s Wrong

  • Missing userId dependency

🤯 Why

  • Effect runs only once → stale data if userId changes

✅ Fix

useEffect(() => {
  fetchUser(userId);
}, [userId]);

💡 Best Practice

  • Follow exhaustive-deps rule

5. 🧠 Derived State Anti-pattern

const [fullName, setFullName] = useState("");

useEffect(() => {
  setFullName(first + " " + last);
}, [first, last]);

❌ What’s Wrong

  • Unnecessary state + effect

🤯 Why

  • Causes extra render cycle

✅ Fix

const fullName = first + " " + last;

💡 Best Practice

  • Avoid derived state in effects

6. ⚡ Over-fetching Due to Object Dependency

useEffect(() => {
  fetchData(filters);
}, [filters]);

❌ What’s Wrong

  • filters recreated → effect runs unnecessarily

🤯 Why

  • Shallow comparison detects new reference

✅ Fix

const memoFilters = useMemo(() => filters, [filters.a, filters.b]);

useEffect(() => {
  fetchData(memoFilters);
}, [memoFilters]);

💡 Best Practice

  • Stabilize dependencies with useMemo

7. 🧨 Race Condition in API Calls

useEffect(() => {
  fetch(`/api?q=${query}`)
    .then(res => res.json())
    .then(setData);
}, [query]);

❌ What’s Wrong

  • Old response may overwrite new one

🤯 Why

  • Async order is not guaranteed

✅ Fix

useEffect(() => {
  const controller = new AbortController();

  fetch(`/api?q=${query}`, { signal: controller.signal })
    .then(res => res.json())
    .then(setData)
    .catch(() => {});

  return () => controller.abort();
}, [query]);

💡 Best Practice

  • Always cancel previous async work

8. 🧩 Missing Cleanup in setTimeout

useEffect(() => {
  setTimeout(() => {
    setVisible(true);
  }, 2000);
}, []);

❌ What’s Wrong

  • Timeout runs even after unmount

🤯 Why

  • No cleanup

✅ Fix

useEffect(() => {
  const id = setTimeout(() => setVisible(true), 2000);
  return () => clearTimeout(id);
}, []);

💡 Best Practice

  • Cleanup all timers

9. ⚠️ useEffect Doing Too Much

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

❌ What’s Wrong

  • Multiple concerns in one effect

🤯 Why

  • Hard to maintain, debug, and optimize

✅ Fix

useEffect(fetchData, []);

useEffect(() => {
  document.title = "Dashboard";
}, []);

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

💡 Best Practice

  • One responsibility per effect

10. 🔄 Infinite Loop via Function Dependency

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

❌ What’s Wrong

  • fetchData recreated every render

🤯 Why

  • Function identity changes

✅ Fix

const fetchData = useCallback(() => {
  // logic
}, []);

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

💡 Best Practice

  • Stabilize functions with useCallback

11. 🧠 Misuse of useLayoutEffect

useLayoutEffect(() => {
  fetchData();
}, []);

❌ What’s Wrong

  • Blocking render unnecessarily

🤯 Why

  • useLayoutEffect runs before paint

✅ Fix

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

💡 Best Practice

  • Use layout effect only for DOM measurement

12. 🧨 Duplicate API Calls in Strict Mode

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

❌ What’s Wrong

  • Runs twice in dev

🤯 Why

  • React Strict Mode double-invokes

✅ Fix

useEffect(() => {
  let ignore = false;

  fetchData().then(data => {
    if (!ignore) setData(data);
  });

  return () => {
    ignore = true;
  };
}, []);

💡 Best Practice

  • Write idempotent effects

13. ⚠️ Missing Dependency in Callback

const handleClick = useCallback(() => {
  console.log(count);
}, []);

❌ What’s Wrong

  • count is stale

🤯 Why

  • Dependency missing

✅ Fix

const handleClick = useCallback(() => {
  console.log(count);
}, [count]);

💡 Best Practice

  • Include all dependencies

14. 🐛 State Update After Unmount

useEffect(() => {
  fetchData().then(setData);
}, []);

❌ What’s Wrong

  • Updates after unmount

🤯 Why

  • Async completes late

✅ Fix

useEffect(() => {
  let mounted = true;

  fetchData().then(data => {
    if (mounted) setData(data);
  });

  return () => {
    mounted = false;
  };
}, []);

💡 Best Practice

  • Guard async updates

15. ⚡ Performance Issue from Frequent Effects

useEffect(() => {
  expensiveCalculation();
});

❌ What’s Wrong

  • Runs every render

🤯 Why

  • No dependency array

✅ Fix

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

💡 Best Practice

  • Control execution frequency

16. 🧩 Incorrect Cleanup Order Assumption

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

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

❌ Misunderstanding

  • Developers expect cleanup after new effect

🤯 Reality

  • Cleanup runs before next effect

💡 Best Practice

  • Understand lifecycle order:
    cleanup → new effect

🔚 Final Insight

These bugs represent real production issues:
  • Race conditions
  • Stale closures
  • Dependency mismanagement
  • Memory leaks
  • Performance regressions
👉 Senior engineers:
  • Think in data flow + synchronization
  • Treat lifecycle as controlled side-effect system

🧠 React Component Lifecycle — Real-World Machine Coding Problems (Senior Architect Level)


1. 🧾 Real-Time Search with Debounce + Cancellation

📌 Requirements

  • Search input with API results
  • Debounce input (300ms)
  • Cancel previous request on new input
  • Show loading + error states

🖥️ UI Behavior

  • Typing → delayed API call
  • Fast typing → only latest request processed
  • Show spinner while fetching

🔄 State / Data Flow

  • query → triggers effect
  • Effect handles:
    • debounce timer
    • API call
    • cleanup (abort)

⚠️ Edge Cases

  • Empty input
  • Rapid typing
  • Slow API responses (race conditions)

⚡ Performance

  • Avoid unnecessary API calls
  • Prevent stale data overwrite

🏗️ Suggested Architecture

  • useEffect for debounce + fetch
  • AbortController for cancellation
  • Separate UI and data logic (custom hook)

🧠 Approach

  1. Store query in state
  2. Debounce with setTimeout
  3. Abort previous fetch
  4. Cleanup on re-run

2. 📡 Live Stock Price Dashboard

📌 Requirements

  • Fetch stock prices every 2 seconds
  • Pause/resume updates
  • Highlight changed values

🖥️ UI Behavior

  • Auto-updating prices
  • Button to pause updates

🔄 State Flow

  • Interval lifecycle controls polling
  • Track previous prices for diffing

⚠️ Edge Cases

  • Multiple intervals
  • Component unmount
  • Network failure

⚡ Performance

  • Avoid unnecessary re-renders
  • Batch updates

🏗️ Architecture

  • useEffect with interval
  • useRef for previous values

🧠 Approach

  1. Start interval on mount
  2. Clear interval on unmount
  3. Compare previous vs current prices

3. 📦 Infinite Scroll Feed (Like Instagram)

📌 Requirements

  • Load posts when scrolling near bottom
  • Prevent duplicate fetches
  • Maintain scroll position

🖥️ UI Behavior

  • Smooth loading
  • Loading indicator at bottom

🔄 State Flow

  • page state triggers API
  • Observer detects viewport

⚠️ Edge Cases

  • Fast scrolling
  • Duplicate API calls
  • End of data

⚡ Performance

  • Use IntersectionObserver
  • Avoid scroll event listeners

🏗️ Architecture

  • Custom hook for observer
  • Effect handles fetching

🧠 Approach

  1. Observe sentinel element
  2. Fetch next page
  3. Cleanup observer

4. 🔔 Notification System (Real-Time)

📌 Requirements

  • Subscribe to WebSocket
  • Display incoming notifications
  • Clean up on unmount

🔄 State Flow

  • WebSocket → pushes data → updates state

⚠️ Edge Cases

  • Reconnect logic
  • Duplicate messages
  • Memory leaks

⚡ Performance

  • Avoid re-subscribing unnecessarily

🏗️ Architecture

  • Effect manages socket lifecycle
  • Separate hook for subscription

🧠 Approach

  1. Connect socket on mount
  2. Listen for messages
  3. Disconnect on unmount

5. 🧠 Form Auto-Save Draft (Google Docs Style)

📌 Requirements

  • Save draft every 2 seconds if changes exist
  • Show “Saving…” and “Saved”

⚠️ Edge Cases

  • Rapid typing
  • Offline mode
  • API failure

⚡ Performance

  • Avoid redundant saves

🏗️ Architecture

  • Compare current vs last saved state
  • Interval-based effect

🧠 Approach

  1. Track dirty state
  2. Run interval
  3. Save only if changed

6. 🎥 Video Player with Lifecycle Sync

📌 Requirements

  • Sync play/pause state with UI
  • Pause video on unmount

⚠️ Edge Cases

  • Tab switch
  • Component remount

🏗️ Architecture

  • useEffect to sync DOM video element

🧠 Approach

  • Use ref
  • Control video via effect

7. 🌐 Multi-Tab Sync (localStorage)

📌 Requirements

  • Sync state across browser tabs

🔄 State Flow

  • storage event listener

⚠️ Edge Cases

  • Infinite update loop
  • Same-tab updates

🏗️ Architecture

  • Effect adds storage listener

🧠 Approach

  • Listen for storage changes
  • Update state conditionally

8. 📍 Geolocation Tracker

📌 Requirements

  • Track user location in real-time
  • Stop tracking on unmount

⚠️ Edge Cases

  • Permission denied
  • High-frequency updates

🏗️ Architecture

  • Effect manages navigator.geolocation.watchPosition

🧠 Approach

  • Subscribe on mount
  • Clear watch on unmount

9. 🧾 Dynamic Form Builder

📌 Requirements

  • Add/remove fields dynamically
  • Validate on change

⚠️ Edge Cases

  • Validation loops
  • stale state

🏗️ Architecture

  • Separate validation effect

🧠 Approach

  • Store form schema
  • Trigger validation effect

10. 🔄 Retry Failed API with Backoff

📌 Requirements

  • Retry API up to 3 times
  • Exponential delay

⚠️ Edge Cases

  • Infinite retries
  • component unmount

🏗️ Architecture

  • Effect + recursive retry

🧠 Approach

  • Track retry count
  • Cleanup pending retries

11. 🧠 Undo/Redo State System

📌 Requirements

  • Maintain history
  • Undo/redo actions

⚠️ Edge Cases

  • Memory growth
  • state sync

🏗️ Architecture

  • Use reducer + effect for side effects

🧠 Approach

  • Store history stack
  • Update on state change

12. 🧾 Smart Table with Server Pagination

📌 Requirements

  • Fetch data on page change
  • Cache previous pages

⚠️ Edge Cases

  • duplicate requests
  • stale data

🏗️ Architecture

  • Cache layer + effect

🧠 Approach

  • Store cache in ref
  • fetch only if not cached

13. 🧪 A/B Testing Variant Loader

📌 Requirements

  • Fetch variant config
  • Apply experiment

⚠️ Edge Cases

  • flicker before load
  • race conditions

🏗️ Architecture

  • blocking vs non-blocking effect

🧠 Approach

  • load config early
  • fallback UI

14. 🧭 Route Change Analytics Tracker

📌 Requirements

  • Track page views on route change

⚠️ Edge Cases

  • duplicate tracking
  • fast navigation

🏗️ Architecture

  • Effect watching route

🧠 Approach

  • debounce tracking
  • track only meaningful changes

15. 📊 Live Chart with Streaming Data

📌 Requirements

  • Update chart in real-time
  • limit data points

⚠️ Edge Cases

  • memory overflow
  • UI lag

🏗️ Architecture

  • interval + sliding window

🧠 Approach

  • push new data
  • remove old data

16. 🧠 Feature Flag System

📌 Requirements

  • Dynamically enable features

⚠️ Edge Cases

  • flicker
  • stale config

🏗️ Architecture

  • global state + effect

🧠 Approach

  • fetch config
  • conditionally render

17. 🔐 Session Timeout Handler

📌 Requirements

  • Auto logout after inactivity

⚠️ Edge Cases

  • multiple timers
  • background tab

🏗️ Architecture

  • event listeners + timer

🧠 Approach

  • reset timer on activity
  • cleanup listeners

18. 📥 File Upload with Progress

📌 Requirements

  • Show upload progress
  • cancel upload

⚠️ Edge Cases

  • cancel mid-upload
  • retry

🏗️ Architecture

  • effect manages upload lifecycle

🧠 Approach

  • track progress
  • abort controller

19. 🧠 Virtualized List (Performance)

📌 Requirements

  • Render only visible items

⚠️ Edge Cases

  • scroll jump
  • dynamic height

🏗️ Architecture

  • effect handles scroll events

🧠 Approach

  • calculate visible range
  • render subset

🔚 Final Insight

These problems test:
  • Lifecycle as synchronization engine
  • Managing:
    • async work
    • subscriptions
    • performance
    • cleanup
  • Designing scalable architecture

🧠 React Component Lifecycle — FAANG-Level Interview Questions


1. Lifecycle vs Synchronization Model

❓ Question

React docs say “think in effects, not lifecycle.” What does that actually mean?

🔁 Follow-up

  • When would lifecycle thinking break down?
  • Can you give a real-world example?

✅ Strong Answer

Lifecycle is traditionally seen as:
mount → update → unmount
But modern React reframes it as:
synchronizing UI with external systems
Example:
useEffect(() => {
  const socket = connect(roomId);
  return () => socket.disconnect();
}, [roomId]);
Here:
  • Not “on mount”
  • But “whenever roomId changes, sync connection”

❌ Weak Answer

“Lifecycle is just useEffect replacing componentDidMount” 👉 Fails because:
  • Misses conceptual shift
  • No understanding of synchronization model

2. Effect Timing & Rendering Phases

❓ Question

Explain how lifecycle hooks align with React’s render and commit phases.

🔁 Follow-up

  • Why can effects not run during render?
  • What happens in concurrent rendering?

✅ Strong Answer

  • Render phase: pure calculation (can be interrupted)
  • Commit phase: DOM updates + effects run
Effects run only after commit → ensures UI consistency

❌ Weak Answer

“useEffect runs after render” 👉 Too shallow; doesn’t explain phases or concurrency

3. Designing a Data Fetching Strategy

❓ Question

How would you design data fetching in a component with changing inputs?

🔁 Follow-up

  • How do you avoid race conditions?
  • How do you handle caching?

✅ Strong Answer

  • Use useEffect with dependencies
  • Cancel previous requests (AbortController)
  • Handle stale responses
  • Possibly move to data layer (React Query)

❌ Weak Answer

“Call fetch inside useEffect” 👉 Ignores:
  • cancellation
  • caching
  • race conditions

4. Debugging Infinite Effect Loops

❓ Question

You see an effect causing repeated API calls. How do you debug it?

🔁 Follow-up

  • What tools or logs would you use?
  • How do dependencies play a role?

✅ Strong Answer

  • Check dependency array
  • Look for:
    • object/function dependencies
    • state updates inside effect
  • Use console + React DevTools

❌ Weak Answer

“Just add []” 👉 Dangerous blanket fix

5. Stale Closures in Production

❓ Question

Explain a real-world bug caused by stale closures and how to fix it.

🔁 Follow-up

  • Why doesn’t React auto-fix this?
  • When should you use refs vs dependencies?

✅ Strong Answer

  • Closure captures old values
  • Example: interval logging old state
  • Fix via:
    • dependencies OR
    • functional updates OR
    • refs

❌ Weak Answer

“Just add dependency” 👉 Not always correct (can cause loops)

6. Strict Mode Behavior

❓ Question

Why does React double-run effects in development?

🔁 Follow-up

  • What kind of bugs does it expose?
  • Should you “fix” double execution?

✅ Strong Answer

  • React Strict Mode simulates mount/unmount cycles
  • Detects unsafe side effects
  • Ensures idempotent effects

❌ Weak Answer

“It’s a bug in React” 👉 Shows lack of understanding

7. Choosing Between useEffect vs useLayoutEffect

❓ Question

When would you choose useLayoutEffect over useEffect?

🔁 Follow-up

  • What performance risks exist?
  • Give a real UI bug example

✅ Strong Answer

  • useLayoutEffect for:
    • DOM measurement
    • preventing flicker
  • Avoid for async work

❌ Weak Answer

“They are the same” 👉 Incorrect and risky

8. Derived State vs Effects

❓ Question

When is using useEffect for derived state a bad idea?

🔁 Follow-up

  • What’s the cost of doing it wrong?

✅ Strong Answer

  • Causes extra render cycle
  • Should compute during render instead

❌ Weak Answer

“It works fine” 👉 Ignores performance + correctness

9. Designing Reusable Lifecycle Logic

❓ Question

How do you abstract lifecycle logic across components?

🔁 Follow-up

  • Trade-offs of custom hooks?
  • When NOT to abstract?

✅ Strong Answer

  • Use custom hooks
  • Encapsulate side effects
Example:
function useInterval(callback, delay) {
  useEffect(() => {
    const id = setInterval(callback, delay);
    return () => clearInterval(id);
  }, [callback, delay]);
}

❌ Weak Answer

“Copy-paste useEffect”

10. Handling Async Side Effects Safely

❓ Question

How do you prevent updating state after unmount?

🔁 Follow-up

  • How does AbortController compare to flags?

✅ Strong Answer

  • Use:
    • AbortController (preferred)
    • or mounted flag
  • Cleanup cancels async work

❌ Weak Answer

“React handles it” 👉 False

11. Performance Bottlenecks from Effects

❓ Question

How can misuse of lifecycle cause performance issues?

🔁 Follow-up

  • How would you detect this?

✅ Strong Answer

  • Over-fetching
  • unnecessary re-renders
  • heavy computations in effects
Use:
  • profiling tools
  • memoization

❌ Weak Answer

“Effects are cheap”

12. Dependency Array Design

❓ Question

How do you decide what goes into a dependency array?

🔁 Follow-up

  • When is it okay to ignore ESLint warnings?

✅ Strong Answer

  • Include all values used
  • Understand identity vs value
  • Rarely suppress warnings (only when safe)

❌ Weak Answer

“Add only what you want”

13. Lifecycle in Concurrent Rendering

❓ Question

How does lifecycle behave differently in concurrent React?

🔁 Follow-up

  • What problems does it solve?

✅ Strong Answer

  • Effects run only for committed renders
  • Prevents inconsistent UI

❌ Weak Answer

“No difference”

14. Real-world Bug: Duplicate API Calls

❓ Question

Your API is called twice on mount. Why?

🔁 Follow-up

  • How would you confirm it?

✅ Strong Answer

  • Strict Mode double invoke
  • OR multiple mounts
  • OR dependency issues

❌ Weak Answer

“React bug”

15. Event Listener Lifecycle Design

❓ Question

How do you safely manage global event listeners?

🔁 Follow-up

  • What happens if handler changes?

✅ Strong Answer

  • Add/remove in effect
  • Ensure stable handler reference

❌ Weak Answer

“Add once”

16. Handling Rapid Prop Changes

❓ Question

Component receives rapidly changing props triggering effects. How do you handle it?

🔁 Follow-up

  • Debounce vs throttle?

✅ Strong Answer

  • Debounce input
  • Cancel previous work
  • Avoid race conditions

❌ Weak Answer

“Let it run”

17. Lifecycle vs State Management Libraries

❓ Question

When should lifecycle logic move out of components?

🔁 Follow-up

  • Compare React Query / Redux

✅ Strong Answer

  • Complex async → move to data layer
  • Reduces duplication

❌ Weak Answer

“Always keep in component”

18. Debugging Memory Leaks

❓ Question

How do you identify and fix lifecycle-related memory leaks?

🔁 Follow-up

  • Tools you’d use?

✅ Strong Answer

  • Look for:
    • missing cleanup
    • intervals
    • listeners
  • Use DevTools profiling

❌ Weak Answer

“React handles cleanup”

19. Designing Lifecycle for Large Systems

❓ Question

How do you manage lifecycle complexity in large apps?

🔁 Follow-up

  • What patterns scale well?

✅ Strong Answer

  • Custom hooks
  • separation of concerns
  • data layer abstraction
  • avoid effect chaining

❌ Weak Answer

“Use more useEffect”

🔚 Final Insight

A senior-level understanding means:
  • Lifecycle = synchronization model
  • Effects = controlled side effects
  • Focus on:
    • correctness
    • performance
    • predictability
👉 Strong candidates:
  • Think in data flow
  • Avoid unnecessary effects
  • Handle async + cleanup rigorously