๐ Class Lifecycle Methods
๐ญ Interactive Lifecycle Demo
๐ฑ Mounting
Birth
๐ Updating
Growth
๐ Unmounting
Death
Component Status: Not Mounted
๐ Class Lifecycle Methods Table
| Phase | Method | Purpose |
|---|---|---|
| Mounting | constructor() | Initialize state aur bind methods |
| static getDerivedStateFromProps() | Props se state derive karna | |
| render() | JSX return karna | |
| componentDidMount() | API calls, subscriptions setup | |
| Updating | static getDerivedStateFromProps() | Props changes handle karna |
| shouldComponentUpdate() | Re-render control karna | |
| render() | Updated JSX return karna | |
| getSnapshotBeforeUpdate() | DOM update se pehle info capture karna | |
| componentDidUpdate() | DOM updates ke baad operations | |
| Unmounting | componentWillUnmount() | Cleanup: timers, subscriptions cancel |
๐ Why Lifecycle Changed in React 16+
โ ๏ธ Deprecated Methods (Ab use mat karo!)
- โ componentWillMount() โ UNSAFE_componentWillMount()
- โ componentWillReceiveProps() โ UNSAFE_componentWillReceiveProps()
- โ componentWillUpdate() โ UNSAFE_componentWillUpdate()
Kyun? Kyunki Fiber architecture mein ye methods multiple times call ho sakte hain, jisse side effects duplicate ho sakte hain!
โ New Safe Alternatives
| Old (Unsafe) | New (Safe) | Reason |
|---|---|---|
| componentWillMount | constructor / componentDidMount | Side effects ko mount ke baad karo |
| componentWillReceiveProps | getDerivedStateFromProps | Pure function, no side effects |
| componentWillUpdate | getSnapshotBeforeUpdate | DOM info capture karne ke liye |
๐ฃ Deep Dive into useEffect
๐ฎ Interactive useEffect Demo
1๏ธโฃ No Dependencies (Har render pe)
Effect runs: 0 times
2๏ธโฃ Empty Dependencies (Sirf mount pe)
Effect runs: 0 times
3๏ธโฃ With Dependencies
Effect runs: 0 times
- No Dependencies: Har baar component render ho, effect chalega
- Empty Array []: Sirf pehli baar (mount pe) effect chalega
- With Dependencies [name]: Jab 'name' change ho, tab effect chalega
๐ useEffect Syntax Variations
๐งน Cleanup Function
Timer Demo with Cleanup
Timer: 0s
๐ชค Dependency Array Traps
- Missing Dependencies: Dependency array mein wo sab values dalo jo effect ke andar use ho rahi hain
- Object/Array Dependencies: Objects aur arrays har render pe naye bante hain, infinite loop ho sakta hai!
- Functions in Dependencies: Functions bhi har render pe naye bante hain
โพ๏ธ Avoiding Infinite Loops
Infinite Loop Demo (Controlled)
Loop Counter: 0
๐ Fetching Data Inside useEffect
Data Fetching Demo
โก useEffect vs useLayoutEffect
- useEffect: Browser ke paint hone ke baad chalta hai (asynchronous)
- useLayoutEffect: Browser ke paint hone se pehle chalta hai (synchronous)
| Feature | useEffect | useLayoutEffect |
|---|---|---|
| Timing | After browser paint | Before browser paint |
| Blocking | Non-blocking (async) | Blocking (sync) |
| Use Case | API calls, subscriptions, most side effects | DOM measurements, preventing visual flicker |
| Performance | Better (doesn't block paint) | Can slow down if heavy operations |
| When to Use | 99% of the time (default choice) | Only when you need to read/write DOM before paint |
- DOM measurements leni ho (scrollHeight, offsetWidth, etc.)
- Visual flicker prevent karni ho
- DOM ko paint se pehle modify karna ho
๐ useInsertionEffect
| Hook | Execution Order | Use Case |
|---|---|---|
| useInsertionEffect | 1๏ธโฃ First (before DOM mutations) | CSS-in-JS libraries only |
| useLayoutEffect | 2๏ธโฃ Second (before browser paint) | DOM measurements, preventing flicker |
| useEffect | 3๏ธโฃ Third (after browser paint) | Most side effects (API calls, subscriptions) |
๐ฏ Interview Questions
Apni understanding test karo! Click karke answers dekho.
Q1: What are the three main phases of a React component lifecycle?
- Mounting: Jab component DOM mein add hota hai (birth)
- Updating: Jab component re-render hota hai due to state/props changes (growth)
- Unmounting: Jab component DOM se remove hota hai (death)
Hinglish: Component ki life teen stages mein hoti hai - paida hona (mounting), bada hona (updating), aur marna (unmounting).
Q2: What is the purpose of the cleanup function in useEffect?
- Cancel subscriptions
- Clear timers (setTimeout, setInterval)
- Remove event listeners
- Abort API requests
- Prevent memory leaks
Hinglish: Cleanup function ka kaam hai safai karna - timers band karna, subscriptions cancel karna, taaki memory leak na ho. Ye component unmount hone se pehle ya next effect run hone se pehle chalta hai.
useEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(timer); // Cleanup!
}, []);
Q3: Why were componentWillMount, componentWillReceiveProps, and componentWillUpdate marked as UNSAFE in React 16+?
- Fiber enables asynchronous rendering - React can pause, abort, or restart rendering
- These methods can be called multiple times before a single render completes
- Side effects in these methods (API calls, subscriptions) can execute multiple times, causing bugs
- They're not "pure" - they can have side effects that don't work well with interruption
Hinglish: React 16 mein Fiber architecture aaya jo rendering ko chhote pieces mein tod sakta hai. Purane "Will" methods beech mein multiple times call ho sakte the, jisse side effects duplicate ho jate the. Isliye inhe UNSAFE mark kar diya aur naye safe alternatives diye gaye.
Q4: What's the difference between useEffect with an empty dependency array [] and no dependency array at all?
| Scenario | When Effect Runs |
|---|---|
useEffect(() => {...}) |
After EVERY render (dangerous!) |
useEffect(() => {...}, []) |
Only ONCE on mount (like componentDidMount) |
Hinglish: Bina dependency array ke effect har render pe chalta hai (bahut dangerous!). Empty array [] ke saath sirf pehli baar mount pe chalta hai. Hamesha dependency array use karo!
Q5: How do you prevent infinite loops when using useEffect?
- Always use dependency array - bina array ke har render pe chalega
- Add conditions - state update se pehle condition check karo
- Use primitive values in dependencies - objects/arrays har render pe naye bante hain
- Use useCallback/useMemo - functions aur objects ko memoize karo
- Don't update dependency inside effect - jo dependency hai use effect ke andar update mat karo (bina condition ke)
// โ Infinite loop
useEffect(() => {
setCount(count + 1);
}, [count]);
// โ
Fixed with condition
useEffect(() => {
if (count < 10) {
setCount(count + 1);
}
}, [count]);
// โ
Better: use functional update
useEffect(() => {
setCount(prev => prev < 10 ? prev + 1 : prev);
}, []); // No dependency on count!
Q6: When should you use useLayoutEffect instead of useEffect? Provide a real-world example.
- Read DOM measurements (scrollHeight, offsetWidth, getBoundingClientRect)
- Prevent visual flicker by updating DOM before paint
- Synchronously re-render based on DOM measurements
Real-world example: Tooltip positioning
function Tooltip({ targetRef, children }) {
const [position, setPosition] = useState({ top: 0, left: 0 });
const tooltipRef = useRef();
useLayoutEffect(() => {
// Measure target element
const targetRect = targetRef.current.getBoundingClientRect();
const tooltipRect = tooltipRef.current.getBoundingClientRect();
// Calculate position to avoid overflow
const top = targetRect.bottom + 10;
const left = targetRect.left - (tooltipRect.width / 2);
setPosition({ top, left });
}, [targetRef]);
return (
<div ref={tooltipRef} style={{ position: 'absolute', ...position }}>
{children}
</div>
);
}
// useLayoutEffect ensures tooltip appears at correct position
// immediately, without flickering at wrong position first
Hinglish: useLayoutEffect tab use karo jab DOM ko measure karna ho aur uske basis pe turant update karna ho, taaki user ko flicker na dikhe. Tooltip, dropdown positioning, scroll animations - yahan use hota hai.
Q7: Explain the race condition problem when fetching data in useEffect and how to solve it.
- User quickly changes input (e.g., search query)
- Multiple API requests fire in sequence
- Responses arrive in different order than requests
- Older response arrives last and overwrites newer data
Solution: Use cleanup function with cancellation flag
function SearchResults({ query }) {
const [results, setResults] = useState([]);
useEffect(() => {
let cancelled = false; // Cancellation flag
async function fetchResults() {
const response = await fetch(`/api/search?q=${query}`);
const data = await response.json();
// Only update if this effect hasn't been cleaned up
if (!cancelled) {
setResults(data);
}
}
fetchResults();
// Cleanup: mark this request as cancelled
return () => {
cancelled = true;
};
}, [query]);
return <div>{results.map(...)}</div>;
}
// Better: Use AbortController (modern approach)
useEffect(() => {
const controller = new AbortController();
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then(res => res.json())
.then(data => setResults(data))
.catch(err => {
if (err.name !== 'AbortError') {
console.error(err);
}
});
return () => controller.abort(); // Cancel request
}, [query]);
Hinglish: Race condition ka matlab hai ki purani request ka response baad mein aa jaye aur nayi data ko overwrite kar de. Solution: cleanup function mein ek flag set karo ya AbortController use karke request cancel karo.