Thursday, January 22, 2026

useEffect in Depth (Complete Guide)

1️⃣ What is useEffect?

useEffect
lets you perform side effects in functional components.

Side effects include:

  • API calls (fetch data)

  • Subscriptions

  • Timers

  • DOM manipulation

  • Logging

  • Cleanup tasks

👉 It replaces lifecycle methods:

  • componentDidMount

  • componentDidUpdate

  • componentWillUnmount


2️⃣ Basic Syntax

useEffect(() => { // side effect code }, [dependencies]);

3️⃣ When Does useEffect Run?

This depends on the dependency array.


4️⃣ Case 1: Run on Every Render (❌ Rarely Used)

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

📌 Runs:

  • On first render

  • On every re-render

⚠️ Avoid unless needed.


5️⃣ Case 2: Run Once (Component Did Mount) ✅ MOST COMMON

useEffect(() => { console.log("Component mounted"); fetchData(); }, []);

📌 Runs:

  • Only once when component loads

✔ Ideal for API calls


6️⃣ Case 3: Run When State/Prop Changes

useEffect(() => { console.log("Email changed:", email); }, [email]);

📌 Runs:

  • On mount

  • Whenever

    email changes


7️⃣ Multiple Dependencies

useEffect(() => { console.log("User updated"); }, [firstName, lastName]);

Runs if any dependency changes.


8️⃣ Real Example: Fetch Data from API

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

✔ Fetch once
✔ Set state
✔ Re-render UI


9️⃣
useEffect
with Cleanup (IMPORTANT)

Used for:

  • Timers

  • Event listeners

  • Subscriptions

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

📌 Cleanup runs when:

  • Component unmounts
  • Dependency changes


10️⃣ Example: Form Validation with
useEffect

useEffect(() => { if (email.includes("@")) { setIsValid(true); } else { setIsValid(false); } }, [email]);

✔ Reacts to input changes
✔ No manual triggers needed


11️⃣ Common Mistake ❌ Infinite Loop

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

🚨 Causes infinite re-renders.

✅ Fix

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

12️⃣ Using Async/Await Correctly

❌ Wrong

useEffect(async () => {});

✅ Correct

useEffect(() => { const fetchData = async () => { const res = await fetch(url); setData(await res.json()); }; fetchData(); }, []);

13️⃣ Real CRUD Example (Your Case)

useEffect(() => { fetch("http://localhost/weblession/phpreactcurd/api/fetch.php") .then(res => res.json()) .then(data => setUsers(data)); }, []);

14️⃣ When NOT to Use
useEffect

❌ Deriving state
❌ Handling simple events
❌ Direct calculations


15️⃣ Best Practices

✔ Keep effects focused
✔ One responsibility per effect
✔ Clean up side effects
✔ Correct dependency array


16️⃣ Mental Model (Remember This)

useEffect = React watches values → runs effect when they change


17️⃣ Comparison with Lifecycle Methods

Class ComponentuseEffect
componentDidMount
useEffect(() => {}, [])
componentDidUpdate
useEffect(() => {}, [deps])
componentWillUnmountCleanup function

🎯 Summary

ConceptRule
Side effectsuseEffect
Dependency arrayControls execution
CleanupPrevent memory leaks
AsyncUse inner function
Infinite loopWatch dependencies

1️⃣
useEffect
Dependency Rules (VERY IMPORTANT)

Basic Rule

Every value used inside

useEffect
that can change must be listed in the dependency array.

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

🔹 Rule 1: Empty Dependency
[]

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

✔ Runs once
✔ Equivalent to

componentDidMount

Use when:

  • API call on page load

  • Initial setup


🔹 Rule 2: Specific Dependencies

useEffect(() => { validateEmail(email); }, [email]);

✔ Runs when

email
changes
✔ React watches
email


🔹 Rule 3: Multiple Dependencies

useEffect(() => { console.log("User changed"); }, [firstName, lastName]);

✔ Runs when any dependency changes


🔹 Rule 4: NO Dependency Array (Avoid)

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

❌ Runs on every render
❌ Performance issues


🔹 Rule 5: Functions as Dependencies

❌ Problem:

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

✔ Fix with

useCallback

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

🔹 Rule 6: Objects & Arrays

Objects change reference on every render.

❌ Bad:

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

✔ Good:

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

🔹 Golden Rule (Interview Line ⭐)

If it’s used inside

useEffect
and can change, it belongs in the dependency array.


2️⃣ Real
useEffect
Interview Questions (with Answers)

Q1. Why does
useEffect
cause infinite loop?

Answer:
Because state is updated inside

useEffect
and that state is listed as a dependency.


Q2. How do you run
useEffect
only once?

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

Q3. Can we use async directly in
useEffect
?

❌ No
✔ Use async function inside effect


Q4. What happens if dependency array is missing?

Effect runs on every render.


Q5. How does cleanup work?

useEffect(() => { return () => cleanup(); }, []);

Runs on unmount or before re-run.


Q6. Difference between
useEffect
and lifecycle methods?

useEffect
combines:

  • componentDidMount

  • componentDidUpdate

  • componentWillUnmount


Q7. Why React warns about missing dependencies?

To prevent stale values and bugs.


3️⃣ Full React + PHP CRUD Flow (End-to-End)

🔹 Step 1: React Form

const [user, setUser] = useState({ first_name: "", last_name: "", email: "" });

🔹 Step 2: Submit (CREATE)

fetch("api/create.php", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(user) });

🔹 Step 3: PHP Create API

$data = json_decode(file_get_contents("php://input")); $stmt = mysqli_prepare( $conn, "INSERT INTO users (first_name, last_name, email) VALUES (?, ?, ?)" ); mysqli_stmt_bind_param( $stmt, "sss", $data->first_name, $data->last_name, $data->email ); mysqli_stmt_execute($stmt);

🔹 Step 4: FETCH (READ)

React

useEffect(() => { fetch("api/read.php") .then(res => res.json()) .then(data => setUsers(data)); }, []);

🔹 Step 5: UPDATE

fetch("api/update.php", { method: "PUT", body: JSON.stringify(user) });

🔹 Step 6: DELETE

fetch(`api/delete.php?id=${id}`, { method: "DELETE" });

🔹 CRUD Flow Diagram

React UI ↓ handleSubmit ↓ fetch API ↓ PHP API ↓ MySQL ↓ JSON Response ↓ React State Update

4️⃣
useEffect
vs
useLayoutEffect
(VERY IMPORTANT)

FeatureuseEffectuseLayoutEffect
ExecutionAfter paintBefore paint
UI blocking❌ No✔ Yes
PerformanceBetterSlower
Use caseAPI, logsDOM measurements

🔹 Example Difference

useEffect

useEffect(() => { console.log(divRef.current.offsetHeight); }, []);

⚠️ UI may flicker


useLayoutEffect

useLayoutEffect(() => { console.log(divRef.current.offsetHeight); }, []);

✔ Accurate measurement
✔ No flicker


🔹 When to Use What?

useEffect → 90% cases
useLayoutEffect → DOM size, animations


No comments:

Post a Comment

If you have any problem please let me know.