📚 Performance Optimization Kya Hai?
Performance Optimization ka matlab hai apne React application ko itna fast banana ki user ko lag hi na pade ki kuch load ho raha hai. Yeh sirf code likhna nahi hai, balki smart code likhna hai jo unnecessary re-renders avoid kare, memory efficiently use kare, aur user experience ko smooth rakhe.
React by default bahut fast hai, lekin jab application badi ho jati hai, tab performance issues aa sakte hain. Isliye hume optimization techniques seekhni zaroori hai.
React by default bahut fast hai, lekin jab application badi ho jati hai, tab performance issues aa sakte hain. Isliye hume optimization techniques seekhni zaroori hai.
🎯 Performance Kyun Important Hai?
- User Experience: Fast apps = Happy users = Better retention
- SEO Rankings: Google slow websites ko penalize karta hai
- Conversion Rates: 1 second delay = 7% conversion loss
- Mobile Users: Slow networks pe bhi smooth experience
- Resource Efficiency: Kam CPU aur memory usage
53%
Users leave if load > 3s
100ms
Delay feels instant
1s
User flow interrupted
10s
User gives up
💡 Real-World Impact: Amazon found that every 100ms of latency cost them 1% in sales. Pinterest reduced load time by 40% and saw 15% increase in sign-ups. Performance directly impacts business!
1️⃣ React.memo - Component Memoization
React.memo ek Higher Order Component (HOC) hai jo component ko wrap karke uske unnecessary re-renders ko prevent karta hai. Jab parent component re-render hota hai, tab by default saare child components bhi re-render hote hain, chahe unke props change hue ho ya nahi.
React.memo props ko compare karta hai aur agar same hain toh re-render skip kar deta hai.
// Without React.memo - Har baar re-render hoga
const ExpensiveComponent = ({ data }) => {
console.log('ExpensiveComponent rendered');
// Heavy computation
const result = data.map(item => {
// Complex calculations...
return item * 2;
});
return <div>{result.join(', ')}</div>;
};
// With React.memo - Sirf jab props change ho tab re-render
const ExpensiveComponent = React.memo(({ data }) => {
console.log('ExpensiveComponent rendered');
const result = data.map(item => item * 2);
return <div>{result.join(', ')}</div>;
});
// Custom comparison function
const ExpensiveComponent = React.memo(
({ data, config }) => {
return <div>{/* Component JSX */}</div>;
},
(prevProps, nextProps) => {
// Return true if props are equal (skip re-render)
// Return false if props are different (re-render)
return prevProps.data.length === nextProps.data.length &&
prevProps.config.id === nextProps.config.id;
}
);
🎮 Interactive Demo: React.memo in Action
Parent component ko re-render karo aur dekho kaise React.memo unnecessary re-renders prevent karta hai:
❌ Without React.memo
Parent Renders: 0
Child Renders: 0
Har parent render pe child bhi render hota hai!
✅ With React.memo
Parent Renders: 0
Child Renders: 0
Sirf jab props change ho tab child render hota hai!
📊 Performance Savings:
0% renders saved
⚠️ React.memo Kab Use Karein:
✅ Use karo jab:
• Component frequently re-render hota hai
• Component expensive computations karta hai
• Props rarely change hote hain
• Large lists mein items render kar rahe ho
❌ Use mat karo jab:
• Component already fast hai
• Props har baar change hote hain
• Simple components jo kuch compute nahi karte
• Premature optimization (pehle measure karo!)
✅ Use karo jab:
• Component frequently re-render hota hai
• Component expensive computations karta hai
• Props rarely change hote hain
• Large lists mein items render kar rahe ho
❌ Use mat karo jab:
• Component already fast hai
• Props har baar change hote hain
• Simple components jo kuch compute nahi karte
• Premature optimization (pehle measure karo!)
2️⃣ useCallback & useMemo Deep Dive
useCallback aur useMemo dono hooks hain jo values ko memoize karte hain, lekin different purposes ke liye:
• useCallback: Functions ko memoize karta hai (function reference same rehta hai)
• useMemo: Computed values ko memoize karta hai (expensive calculations cache karta hai)
• useCallback: Functions ko memoize karta hai (function reference same rehta hai)
• useMemo: Computed values ko memoize karta hai (expensive calculations cache karta hai)
useCallback - Function Memoization
// Problem: Har render pe naya function create hota hai
const ParentComponent = () => {
const [count, setCount] = useState(0);
// Yeh function har render pe naya ban raha hai!
const handleClick = () => {
console.log('Clicked!');
};
return (
<>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<ChildComponent onClick={handleClick} />
</>
);
};
// Solution: useCallback se function reference preserve karo
const ParentComponent = () => {
const [count, setCount] = useState(0);
// Function sirf jab dependencies change ho tab recreate hoga
const handleClick = useCallback(() => {
console.log('Clicked!');
}, []); // Empty deps = function kabhi change nahi hoga
return (
<>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<ChildComponent onClick={handleClick} />
</>
);
};
// With dependencies
const SearchComponent = () => {
const [query, setQuery] = useState('');
const [filter, setFilter] = useState('all');
const handleSearch = useCallback(() => {
// Search logic using query and filter
fetchResults(query, filter);
}, [query, filter]); // Recreate jab query ya filter change ho
return <SearchResults onSearch={handleSearch} />;
};
useMemo - Value Memoization
// Problem: Expensive calculation har render pe run hota hai
const DataComponent = ({ items }) => {
const [filter, setFilter] = useState('');
// Yeh calculation har render pe run hoga, even if items same hain!
const expensiveResult = items
.filter(item => item.active)
.map(item => item.value * 2)
.reduce((sum, val) => sum + val, 0);
return <div>{expensiveResult}</div>;
};
// Solution: useMemo se result cache karo
const DataComponent = ({ items }) => {
const [filter, setFilter] = useState('');
// Calculation sirf jab items change ho tab run hoga
const expensiveResult = useMemo(() => {
console.log('Calculating...');
return items
.filter(item => item.active)
.map(item => item.value * 2)
.reduce((sum, val) => sum + val, 0);
}, [items]); // Dependency array
return <div>{expensiveResult}</div>;
};
// Complex example with multiple dependencies
const ChartComponent = ({ data, config }) => {
const chartData = useMemo(() => {
// Heavy data transformation
return data
.filter(d => d.value > config.threshold)
.sort((a, b) => b.value - a.value)
.slice(0, config.limit);
}, [data, config.threshold, config.limit]);
return <Chart data={chartData} />;
};
🎮 Interactive Demo: useCallback vs useMemo
❌ Without Memoization
Renders: 0
Calculations: 0
Function Creates: 0
Time Taken: 0ms
✅ With useCallback & useMemo
Renders: 0
Calculations: 0
Function Creates: 0
Time Taken: 0ms
✅ Best Practices:
useCallback use karo jab:
• Function ko child component mein pass kar rahe ho
• Function dependency hai useEffect ya useMemo mein
• Event handlers jo frequently change nahi hote
useMemo use karo jab:
• Expensive calculations kar rahe ho
• Large data transformations
• Complex filtering/sorting operations
• Object/Array creation jo child props mein jata hai
useCallback use karo jab:
• Function ko child component mein pass kar rahe ho
• Function dependency hai useEffect ya useMemo mein
• Event handlers jo frequently change nahi hote
useMemo use karo jab:
• Expensive calculations kar rahe ho
• Large data transformations
• Complex filtering/sorting operations
• Object/Array creation jo child props mein jata hai
3️⃣ Avoiding Unnecessary Re-renders
React mein re-renders performance ka sabse bada issue hai. Har re-render mein React component function ko execute karta hai, virtual DOM create karta hai, aur real DOM se compare karta hai. Agar yeh unnecessarily ho raha hai, toh app slow ho jata hai. Chaliye dekhte hain common causes aur solutions.
Common Re-render Causes
// 1. State updates in parent cause child re-renders
const Parent = () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<ExpensiveChild /> {/* Unnecessarily re-renders! */}
</>
);
};
// Solution: Move state down or use React.memo
const Parent = () => {
return (
<>
<CounterButton /> {/* State isolated */}
<ExpensiveChild /> {/* Won't re-render */}
</>
);
};
// 2. Creating objects/arrays in render
const BadComponent = () => {
const config = { theme: 'dark' }; // New object every render!
const items = [1, 2, 3]; // New array every render!
return <Child config={config} items={items} />;
};
// Solution: Move outside or use useMemo
const config = { theme: 'dark' }; // Outside component
const GoodComponent = () => {
const items = useMemo(() => [1, 2, 3], []); // Memoized
return <Child config={config} items={items} />;
};
// 3. Context updates cause all consumers to re-render
const App = () => {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
// Problem: Har state change pe sab re-render honge
const value = { user, setUser, theme, setTheme };
return (
<AppContext.Provider value={value}>
<Components />
</AppContext.Provider>
);
};
// Solution: Split contexts
const App = () => {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
const userValue = useMemo(() => ({ user, setUser }), [user]);
const themeValue = useMemo(() => ({ theme, setTheme }), [theme]);
return (
<UserContext.Provider value={userValue}>
<ThemeContext.Provider value={themeValue}>
<Components />
</ThemeContext.Provider>
</UserContext.Provider>
);
};
🎮 Interactive Demo: Re-render Patterns
Component Tree Re-renders:
📦 Parent Component - Renders: 0
📦 Child A (Memoized) - Renders: 0
📦 Child B (Not Memoized) - Renders: 0
📦 Grandchild - Renders: 0
⚡ Performance Metrics:
Total Re-renders:
0
Prevented Re-renders:
0
Performance Gain:
0%
| Pattern | Problem | Solution |
|---|---|---|
| State Lifting | Parent state changes cause all children to re-render | Move state down, use composition, React.memo |
| Inline Objects | New object reference every render | useMemo, move outside component |
| Inline Functions | New function reference every render | useCallback, move outside component |
| Context Updates | All consumers re-render on any context change | Split contexts, memoize values |
| Props Drilling | Intermediate components re-render unnecessarily | Context, composition, state management |
4️⃣ React Profiler Tool
React Profiler ek built-in tool hai jo aapko batata hai ki aapka application kahan slow ho raha hai. Yeh measure karta hai ki har component kitni baar render ho raha hai, kitna time le raha hai, aur kyun render ho raha hai. Production mein performance issues identify karne ke liye yeh bahut powerful tool hai.
// React DevTools Profiler (Browser Extension)
// 1. Install React DevTools extension
// 2. Open DevTools → Profiler tab
// 3. Click record button
// 4. Interact with your app
// 5. Stop recording and analyze
// Programmatic Profiler API
import { Profiler } from 'react';
const onRenderCallback = (
id, // Component ID
phase, // "mount" or "update"
actualDuration, // Time spent rendering
baseDuration, // Estimated time without memoization
startTime, // When React began rendering
commitTime, // When React committed the update
interactions // Set of interactions
) => {
console.log(`${id} took ${actualDuration}ms to render`);
// Send to analytics
analytics.track('component_render', {
component: id,
duration: actualDuration,
phase: phase
});
};
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Navigation />
<Profiler id="Dashboard" onRender={onRenderCallback}>
<Dashboard />
</Profiler>
<Footer />
</Profiler>
);
}
// Custom Performance Hook
const usePerformanceMonitor = (componentName) => {
const renderCount = useRef(0);
const startTime = useRef(null);
useEffect(() => {
renderCount.current += 1;
const renderTime = performance.now() - startTime.current;
console.log(`${componentName} render #${renderCount.current}: ${renderTime}ms`);
});
startTime.current = performance.now();
};
// Usage
const MyComponent = () => {
usePerformanceMonitor('MyComponent');
return <div>Content</div>;
};
🎮 Interactive Demo: Profiler Simulation
📊 Profiler Results:
Component ID:
-
Phase:
-
Actual Duration:
-
Base Duration:
-
Render Count:
0
Performance Score:
-
Performance Breakdown:
💡 Profiler Insights:
Flame Graph: Shows component hierarchy and render times
Ranked Chart: Lists components by render duration
Component Chart: Shows individual component render history
Interactions: Tracks user interactions and their performance impact
What to Look For:
• Components with high render counts
• Long render durations (>16ms for 60fps)
• Unexpected re-renders
• Components that render but don't change
Flame Graph: Shows component hierarchy and render times
Ranked Chart: Lists components by render duration
Component Chart: Shows individual component render history
Interactions: Tracks user interactions and their performance impact
What to Look For:
• Components with high render counts
• Long render durations (>16ms for 60fps)
• Unexpected re-renders
• Components that render but don't change
5️⃣ Windowing Large Lists (Virtualization)
Windowing ya Virtualization ek technique hai jisme aap sirf visible items ko DOM mein render karte ho, baaki items ko skip kar dete ho. Jab user scroll karta hai, tab dynamically items add/remove hote hain. Isse 10,000+ items wali list bhi smooth scroll hoti hai.
Popular libraries: react-window (lightweight) aur react-virtualized (feature-rich)
Popular libraries: react-window (lightweight) aur react-virtualized (feature-rich)
// Without Virtualization - Slow for large lists
const SlowList = ({ items }) => {
return (
<div>
{items.map(item => (
<ListItem key={item.id} data={item} />
))}
</div>
);
};
// With react-window - Fast for any list size
import { FixedSizeList } from 'react-window';
const FastList = ({ items }) => {
const Row = ({ index, style }) => (
<div style={style}>
<ListItem data={items[index]} />
</div>
);
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width={'100%'}
>
{Row}
</FixedSizeList>
);
};
// Variable size items
import { VariableSizeList } from 'react-window';
const DynamicList = ({ items }) => {
const listRef = useRef();
const getItemSize = (index) => {
// Calculate height based on content
return items[index].expanded ? 200 : 50;
};
return (
<VariableSizeList
ref={listRef}
height={600}
itemCount={items.length}
itemSize={getItemSize}
width={'100%'}
>
{Row}
</VariableSizeList>
);
};
// Grid virtualization
import { FixedSizeGrid } from 'react-window';
const ImageGrid = ({ images }) => {
const Cell = ({ columnIndex, rowIndex, style }) => {
const index = rowIndex * 5 + columnIndex;
return (
<div style={style}>
<img src={images[index]} alt="" />
</div>
);
};
return (
<FixedSizeGrid
columnCount={5}
columnWidth={200}
height={600}
rowCount={Math.ceil(images.length / 5)}
rowHeight={200}
width={1000}
>
{Cell}
</FixedSizeGrid>
);
};
🎮 Interactive Demo: Virtualized vs Normal List
❌ Normal List (All Rendered)
Click "Generate List" to start
DOM Nodes: 0
Render Time: 0ms
Memory: 0 MB
Render Time: 0ms
Memory: 0 MB
✅ Virtualized List (Only Visible)
Click "Generate List" to start
DOM Nodes: 0
Render Time: 0ms
Memory: 0 MB
Render Time: 0ms
Memory: 0 MB
📊 Performance Comparison:
Speed Improvement
0x
Memory Saved
0%
DOM Nodes Saved
0%
✅ When to Use Virtualization:
• Lists with 100+ items
• Infinite scroll implementations
• Large data tables
• Image galleries with many images
• Chat applications with long message history
• Any scrollable content with performance issues
Benefits:
• Constant render time regardless of list size
• Minimal DOM nodes (only visible items)
• Smooth scrolling even with 100,000+ items
• Lower memory usage
• Lists with 100+ items
• Infinite scroll implementations
• Large data tables
• Image galleries with many images
• Chat applications with long message history
• Any scrollable content with performance issues
Benefits:
• Constant render time regardless of list size
• Minimal DOM nodes (only visible items)
• Smooth scrolling even with 100,000+ items
• Lower memory usage
6️⃣ Heavy Computation Offloading
Heavy computations main thread ko block kar dete hain, jisse UI freeze ho jata hai. Isko solve karne ke liye hum computations ko background mein move kar sakte hain using Web Workers, ya phir requestIdleCallback use karke idle time mein execute kar sakte hain.
// Problem: Heavy computation blocks UI
const SlowComponent = ({ data }) => {
const [result, setResult] = useState(null);
const processData = () => {
// This blocks the UI thread!
let sum = 0;
for (let i = 0; i < 1000000000; i++) {
sum += Math.sqrt(i);
}
setResult(sum);
};
return <button onClick={processData}>Process</button>;
};
// Solution 1: Web Workers
// worker.js
self.addEventListener('message', (e) => {
const data = e.data;
let sum = 0;
for (let i = 0; i < data.length; i++) {
sum += Math.sqrt(data[i]);
}
self.postMessage(sum);
});
// Component using Web Worker
const FastComponent = ({ data }) => {
const [result, setResult] = useState(null);
const workerRef = useRef(null);
useEffect(() => {
workerRef.current = new Worker('worker.js');
workerRef.current.addEventListener('message', (e) => {
setResult(e.data);
});
return () => workerRef.current.terminate();
}, []);
const processData = () => {
workerRef.current.postMessage(data);
};
return <button onClick={processData}>Process</button>;
};
// Solution 2: requestIdleCallback
const IdleComponent = ({ data }) => {
const [result, setResult] = useState(null);
const processData = () => {
let index = 0;
let sum = 0;
const processChunk = (deadline) => {
while (deadline.timeRemaining() > 0 && index < data.length) {
sum += Math.sqrt(data[index]);
index++;
}
if (index < data.length) {
requestIdleCallback(processChunk);
} else {
setResult(sum);
}
};
requestIdleCallback(processChunk);
};
return <button onClick={processData}>Process</button>;
};
// Solution 3: Time Slicing with setTimeout
const useTimeSlicing = (heavyTask, chunkSize = 1000) => {
const [result, setResult] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const process = async (data) => {
setIsProcessing(true);
let index = 0;
let accumulated = [];
while (index < data.length) {
const chunk = data.slice(index, index + chunkSize);
const chunkResult = await new Promise(resolve => {
setTimeout(() => {
resolve(heavyTask(chunk));
}, 0);
});
accumulated.push(chunkResult);
index += chunkSize;
}
setResult(accumulated);
setIsProcessing(false);
};
return { result, isProcessing, process };
};
🎮 Interactive Demo: Computation Offloading
UI Responsiveness Test:
Try clicking this button while computation is running:
Click the button to test UI responsiveness
Blocking Task
Status: Ready
Time: 0ms
UI Blocked: Yes
Web Worker
Status: Ready
Time: 0ms
UI Blocked: No
Time-Sliced
Status: Ready
Time: 0ms
UI Blocked: No
Progress:
| Technique | Use Case | Pros | Cons |
|---|---|---|---|
| Web Workers | Heavy CPU computations, data processing | True parallelism, UI never blocks | No DOM access, communication overhead |
| requestIdleCallback | Non-urgent background tasks | Runs during idle time, no blocking | Not guaranteed to run, browser support |
| Time Slicing | Long-running tasks that need DOM access | Simple implementation, DOM access | Slower overall, requires chunking logic |
| useMemo | Expensive calculations in render | Easy to use, caches results | Still blocks on first calculation |
7️⃣ Production Performance Patterns
Real-world production applications mein performance optimization ek continuous process hai. Yahan kuch proven patterns hain jo large-scale applications mein use hote hain.
Pattern 1: Component Composition over Props
// ❌ Bad: Props drilling causes unnecessary re-renders
const App = () => {
const [user, setUser] = useState(null);
return (
<Layout user={user}>
<Sidebar user={user} />
<Content user={user} />
</Layout>
);
};
// ✅ Good: Composition prevents unnecessary re-renders
const App = () => {
const [user, setUser] = useState(null);
return (
<Layout>
<Sidebar>
<UserProfile user={user} />
</Sidebar>
<Content />
</Layout>
);
};
Pattern 2: Debouncing & Throttling
// Custom debounce hook
const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
};
// Usage in search
const SearchComponent = () => {
const [query, setQuery] = useState('');
const debouncedQuery = useDebounce(query, 500);
useEffect(() => {
if (debouncedQuery) {
fetchResults(debouncedQuery);
}
}, [debouncedQuery]);
return <input onChange={(e) => setQuery(e.target.value)} />;
};
// Throttle for scroll events
const useThrottle = (callback, delay) => {
const lastRun = useRef(Date.now());
return useCallback((...args) => {
const now = Date.now();
if (now - lastRun.current >= delay) {
callback(...args);
lastRun.current = now;
}
}, [callback, delay]);
};
Pattern 3: Lazy State Initialization
// ❌ Bad: Expensive calculation runs every render
const Component = () => {
const [data, setData] = useState(expensiveCalculation());
// expensiveCalculation() runs on every render!
};
// ✅ Good: Calculation runs only once
const Component = () => {
const [data, setData] = useState(() => expensiveCalculation());
// Function runs only on initial render
};
Pattern 4: Optimistic Updates
// Optimistic UI updates for better perceived performance
const TodoList = () => {
const [todos, setTodos] = useState([]);
const addTodo = async (text) => {
const tempId = Date.now();
const newTodo = { id: tempId, text, pending: true };
// Optimistically add to UI
setTodos(prev => [...prev, newTodo]);
try {
const savedTodo = await api.createTodo(text);
// Replace temp with real data
setTodos(prev =>
prev.map(t => t.id === tempId ? savedTodo : t)
);
} catch (error) {
// Rollback on error
setTodos(prev => prev.filter(t => t.id !== tempId));
}
};
};
✅ Production Checklist:
Before Deployment:
☑️ Run React DevTools Profiler
☑️ Check bundle size with webpack-bundle-analyzer
☑️ Test on slow 3G network
☑️ Measure Core Web Vitals (LCP, FID, CLS)
☑️ Enable production build optimizations
☑️ Implement code splitting for routes
☑️ Add error boundaries
☑️ Set up performance monitoring (Sentry, LogRocket)
Ongoing Monitoring:
📊 Track render counts and durations
📊 Monitor bundle size growth
📊 Watch for memory leaks
📊 Analyze user interaction metrics
📊 Set performance budgets
Before Deployment:
☑️ Run React DevTools Profiler
☑️ Check bundle size with webpack-bundle-analyzer
☑️ Test on slow 3G network
☑️ Measure Core Web Vitals (LCP, FID, CLS)
☑️ Enable production build optimizations
☑️ Implement code splitting for routes
☑️ Add error boundaries
☑️ Set up performance monitoring (Sentry, LogRocket)
Ongoing Monitoring:
📊 Track render counts and durations
📊 Monitor bundle size growth
📊 Watch for memory leaks
📊 Analyze user interaction metrics
📊 Set performance budgets
🎯 Interview Questions
Master these questions to ace your React performance interviews!
Easy
Q1: React.memo kya hai aur yeh kaise kaam karta hai? Kab use karna chahiye?
Answer:
React.memo kya hai:
React.memo ek Higher Order Component (HOC) hai jo component ko memoize karta hai. Yeh shallow comparison karta hai props ka, aur agar props same hain toh component ko re-render nahi karta.
Kaise kaam karta hai:
1. Component ko React.memo se wrap karo
2. Jab parent re-render hota hai, React props compare karta hai
3. Agar props same hain (shallow equality), previous render result reuse hota hai
4. Agar props different hain, component re-render hota hai
Example:
Kab use karein:
✅ Component frequently re-render hota hai
✅ Props rarely change hote hain
✅ Component expensive computations karta hai
✅ Pure functional component hai (same props = same output)
Kab use na karein:
❌ Props har baar change hote hain
❌ Component already fast hai
❌ Simple components jo kuch compute nahi karte
❌ Premature optimization
Custom Comparison:
React.memo kya hai:
React.memo ek Higher Order Component (HOC) hai jo component ko memoize karta hai. Yeh shallow comparison karta hai props ka, aur agar props same hain toh component ko re-render nahi karta.
Kaise kaam karta hai:
1. Component ko React.memo se wrap karo
2. Jab parent re-render hota hai, React props compare karta hai
3. Agar props same hain (shallow equality), previous render result reuse hota hai
4. Agar props different hain, component re-render hota hai
Example:
const ExpensiveComponent = React.memo(({ data }) => {
// Heavy rendering logic
return <div>{data}</div>;
});Kab use karein:
✅ Component frequently re-render hota hai
✅ Props rarely change hote hain
✅ Component expensive computations karta hai
✅ Pure functional component hai (same props = same output)
Kab use na karein:
❌ Props har baar change hote hain
❌ Component already fast hai
❌ Simple components jo kuch compute nahi karte
❌ Premature optimization
Custom Comparison:
const Component = React.memo(
({ data }) => <div>{data}</div>,
(prevProps, nextProps) => {
// Return true to skip re-render
return prevProps.data.id === nextProps.data.id;
}
);
Easy
Q2: useCallback aur useMemo mein kya difference hai? Examples ke saath explain karo.
Answer:
Main Difference:
• useCallback: Function ko memoize karta hai (function reference preserve karta hai)
• useMemo: Function ke result ko memoize karta hai (computed value cache karta hai)
useCallback Example:
useMemo Example:
Kab kaunsa use karein:
useCallback:
• Function ko child component mein pass kar rahe ho
• Function dependency hai useEffect/useMemo mein
• Event handlers jo frequently change nahi hote
useMemo:
• Expensive calculations
• Large data transformations
• Complex filtering/sorting
• Object/Array creation jo props mein jata hai
Memory Trick:
• useCallback = Callback function ko yaad rakho
• useMemo = Memo (memory) mein value store karo
Main Difference:
• useCallback: Function ko memoize karta hai (function reference preserve karta hai)
• useMemo: Function ke result ko memoize karta hai (computed value cache karta hai)
useCallback Example:
// Without useCallback - New function every render
const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log('Clicked');
};
return <Child onClick={handleClick} />;
};
// With useCallback - Same function reference
const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Clicked');
}, []); // Dependencies
return <Child onClick={handleClick} />;
};useMemo Example:
// Without useMemo - Calculation every render
const Component = ({ items }) => {
const total = items.reduce((sum, item) => sum + item.price, 0);
return <div>{total}</div>;
};
// With useMemo - Cached result
const Component = ({ items }) => {
const total = useMemo(() => {
return items.reduce((sum, item) => sum + item.price, 0);
}, [items]); // Recalculate only when items change
return <div>{total}</div>;
};Kab kaunsa use karein:
useCallback:
• Function ko child component mein pass kar rahe ho
• Function dependency hai useEffect/useMemo mein
• Event handlers jo frequently change nahi hote
useMemo:
• Expensive calculations
• Large data transformations
• Complex filtering/sorting
• Object/Array creation jo props mein jata hai
Memory Trick:
• useCallback = Callback function ko yaad rakho
• useMemo = Memo (memory) mein value store karo
Medium
Q3: React mein unnecessary re-renders kaise avoid karein? Common causes aur solutions explain karo.
Answer:
Common Causes aur Solutions:
1. Parent State Changes:
Problem: Parent ka state change hone pe saare children re-render hote hain
Solution:
• State ko neeche move karo (state colocation)
• React.memo use karo children pe
• Component composition use karo
2. Inline Objects/Arrays:
Problem: Har render pe naya reference create hota hai
Solution: useMemo ya component ke bahar move karo
3. Context Updates:
Problem: Context value change hone pe saare consumers re-render
Solution: Context split karo, value memoize karo
4. Inline Functions:
Problem: Har render pe naya function
Solution: useCallback use karo
Best Practices:
✅ React DevTools Profiler use karo to identify issues
✅ Measure before optimizing
✅ State ko jitna possible neeche rakho
✅ Composition over props drilling
✅ Memoization judiciously use karo
Common Causes aur Solutions:
1. Parent State Changes:
Problem: Parent ka state change hone pe saare children re-render hote hain
Solution:
• State ko neeche move karo (state colocation)
• React.memo use karo children pe
• Component composition use karo
// ❌ Bad
const Parent = () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<ExpensiveChild /> {/* Unnecessarily re-renders */}
</>
);
};
// ✅ Good - State moved down
const Parent = () => {
return (
<>
<Counter />
<ExpensiveChild /> {/* Won't re-render */}
</>
);
};2. Inline Objects/Arrays:
Problem: Har render pe naya reference create hota hai
Solution: useMemo ya component ke bahar move karo
// ❌ Bad
const Component = () => {
const config = { theme: 'dark' }; // New object every render
return <Child config={config} />;
};
// ✅ Good
const config = { theme: 'dark' }; // Outside component
const Component = () => {
return <Child config={config} />;
};3. Context Updates:
Problem: Context value change hone pe saare consumers re-render
Solution: Context split karo, value memoize karo
// ❌ Bad
const App = () => {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
const value = { user, setUser, theme, setTheme };
return <Context.Provider value={value}>...</Context.Provider>;
};
// ✅ Good - Split contexts
const App = () => {
const userValue = useMemo(() => ({ user, setUser }), [user]);
const themeValue = useMemo(() => ({ theme, setTheme }), [theme]);
return (
<UserContext.Provider value={userValue}>
<ThemeContext.Provider value={themeValue}>...</ThemeContext.Provider>
</UserContext.Provider>
);
};4. Inline Functions:
Problem: Har render pe naya function
Solution: useCallback use karo
Best Practices:
✅ React DevTools Profiler use karo to identify issues
✅ Measure before optimizing
✅ State ko jitna possible neeche rakho
✅ Composition over props drilling
✅ Memoization judiciously use karo
Medium
Q4: React Profiler tool kaise use karte hain? Production mein performance issues kaise identify karein?
Answer:
React Profiler Tool:
React DevTools ka ek part hai jo component render performance measure karta hai.
Kaise Use Karein:
1. Install: React DevTools browser extension
2. Open: DevTools → Profiler tab
3. Record: Record button click karo
4. Interact: App ke saath interact karo
5. Stop: Recording stop karo
6. Analyze: Results dekho
Profiler Views:
1. Flame Graph:
• Component hierarchy dikhata hai
• Render time by color (green = fast, yellow = slow, red = very slow)
• Width = time spent rendering
• Click karke details dekho
2. Ranked Chart:
• Components sorted by render duration
• Slowest components pehle
• Optimization priorities identify karo
3. Component Chart:
• Individual component ka render history
• Har render ka duration
• Why did this render? information
Programmatic Profiler:
Performance Issues Identify Karna:
Red Flags:
🚩 Components with high render counts
🚩 Render duration > 16ms (60fps ke liye)
🚩 Unexpected re-renders
🚩 Components that render but don't change
🚩 Large component trees rendering together
Analysis Steps:
1. Identify slowest components (Ranked view)
2. Check why they're rendering (Component view)
3. Look for unnecessary re-renders
4. Check parent-child render patterns
5. Measure before and after optimization
Production Monitoring:
• Use Profiler API to send metrics to analytics
• Track Core Web Vitals (LCP, FID, CLS)
• Set up performance budgets
• Use tools like Lighthouse, WebPageTest
• Monitor with Sentry, LogRocket, etc.
React Profiler Tool:
React DevTools ka ek part hai jo component render performance measure karta hai.
Kaise Use Karein:
1. Install: React DevTools browser extension
2. Open: DevTools → Profiler tab
3. Record: Record button click karo
4. Interact: App ke saath interact karo
5. Stop: Recording stop karo
6. Analyze: Results dekho
Profiler Views:
1. Flame Graph:
• Component hierarchy dikhata hai
• Render time by color (green = fast, yellow = slow, red = very slow)
• Width = time spent rendering
• Click karke details dekho
2. Ranked Chart:
• Components sorted by render duration
• Slowest components pehle
• Optimization priorities identify karo
3. Component Chart:
• Individual component ka render history
• Har render ka duration
• Why did this render? information
Programmatic Profiler:
import { Profiler } from 'react';
const onRenderCallback = (
id, // Component ID
phase, // "mount" or "update"
actualDuration, // Time spent rendering
baseDuration, // Estimated time without memoization
startTime, // When React began rendering
commitTime // When React committed
) => {
console.log(`${id} took ${actualDuration}ms`);
// Send to analytics
analytics.track('render', {
component: id,
duration: actualDuration,
phase: phase
});
};
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Dashboard />
</Profiler>
);
}Performance Issues Identify Karna:
Red Flags:
🚩 Components with high render counts
🚩 Render duration > 16ms (60fps ke liye)
🚩 Unexpected re-renders
🚩 Components that render but don't change
🚩 Large component trees rendering together
Analysis Steps:
1. Identify slowest components (Ranked view)
2. Check why they're rendering (Component view)
3. Look for unnecessary re-renders
4. Check parent-child render patterns
5. Measure before and after optimization
Production Monitoring:
• Use Profiler API to send metrics to analytics
• Track Core Web Vitals (LCP, FID, CLS)
• Set up performance budgets
• Use tools like Lighthouse, WebPageTest
• Monitor with Sentry, LogRocket, etc.
Hard
Q5: List virtualization kya hai? React Window aur React Virtualized mein difference kya hai? Implementation explain karo.
Answer:
List Virtualization Kya Hai:
Virtualization ek technique hai jisme sirf visible items ko DOM mein render karte hain. Jab user scroll karta hai, items dynamically add/remove hote hain. Isse 10,000+ items wali list bhi smooth scroll hoti hai.
Kaise Kaam Karta Hai:
1. Calculate visible area (viewport)
2. Determine which items are visible
3. Render only those items
4. Add padding to maintain scroll height
5. On scroll, recalculate and update
React Window vs React Virtualized:
React Window Implementation:
Variable Size Items:
Grid Virtualization:
Performance Benefits:
• Constant render time (O(1) instead of O(n))
• Minimal DOM nodes (~20 instead of 10,000)
• Lower memory usage
• Smooth 60fps scrolling
• Works with millions of items
When to Use:
✅ Lists with 100+ items
✅ Infinite scroll
✅ Large data tables
✅ Image galleries
✅ Chat message history
✅ Any scrollable content with performance issues
List Virtualization Kya Hai:
Virtualization ek technique hai jisme sirf visible items ko DOM mein render karte hain. Jab user scroll karta hai, items dynamically add/remove hote hain. Isse 10,000+ items wali list bhi smooth scroll hoti hai.
Kaise Kaam Karta Hai:
1. Calculate visible area (viewport)
2. Determine which items are visible
3. Render only those items
4. Add padding to maintain scroll height
5. On scroll, recalculate and update
React Window vs React Virtualized:
| Feature | React Window | React Virtualized |
|---|---|---|
| Bundle Size | ~6 KB | ~27 KB |
| Features | Basic, focused | Comprehensive |
| Learning Curve | Easy | Moderate |
| Use Case | Simple lists | Complex UIs |
React Window Implementation:
import { FixedSizeList } from 'react-window';
const MyList = ({ items }) => {
const Row = ({ index, style }) => (
<div style={style}>
Item {items[index].name}
</div>
);
return (
<FixedSizeList
height={600} // Container height
itemCount={items.length}
itemSize={50} // Each item height
width="100%"
>
{Row}
</FixedSizeList>
);
};Variable Size Items:
import { VariableSizeList } from 'react-window';
const DynamicList = ({ items }) => {
const listRef = useRef();
const getItemSize = (index) => {
// Dynamic height based on content
return items[index].expanded ? 200 : 50;
};
return (
<VariableSizeList
ref={listRef}
height={600}
itemCount={items.length}
itemSize={getItemSize}
width="100%"
>
{Row}
</VariableSizeList>
);
};Grid Virtualization:
import { FixedSizeGrid } from 'react-window';
const ImageGrid = ({ images }) => {
const Cell = ({ columnIndex, rowIndex, style }) => {
const index = rowIndex * 5 + columnIndex;
return (
<div style={style}>
<img src={images[index]} />
</div>
);
};
return (
<FixedSizeGrid
columnCount={5}
columnWidth={200}
height={600}
rowCount={Math.ceil(images.length / 5)}
rowHeight={200}
width={1000}
>
{Cell}
</FixedSizeGrid>
);
};Performance Benefits:
• Constant render time (O(1) instead of O(n))
• Minimal DOM nodes (~20 instead of 10,000)
• Lower memory usage
• Smooth 60fps scrolling
• Works with millions of items
When to Use:
✅ Lists with 100+ items
✅ Infinite scroll
✅ Large data tables
✅ Image galleries
✅ Chat message history
✅ Any scrollable content with performance issues
Hard
Q6: Web Workers kya hain? React mein heavy computations ko kaise offload karein? Complete implementation explain karo.
Answer:
Web Workers Kya Hain:
Web Workers JavaScript ko background thread mein run karne dete hain, main UI thread ko block kiye bina. Yeh true parallelism provide karte hain aur heavy computations ke liye perfect hain.
Key Features:
• Separate thread mein run hote hain
• Main thread ko block nahi karte
• No DOM access (security reasons)
• Message passing through postMessage
• Can import other scripts
Complete Implementation:
Step 1: Create Worker File (worker.js):
Step 2: Custom Hook for Worker:
Step 3: Use in Component:
Alternative: Time Slicing (Without Workers):
requestIdleCallback Approach:
Comparison:
Best Practices:
✅ Use Workers for CPU-intensive tasks
✅ Keep worker code separate and focused
✅ Handle errors gracefully
✅ Terminate workers when done
✅ Consider worker pool for multiple tasks
✅ Measure performance before/after
Web Workers Kya Hain:
Web Workers JavaScript ko background thread mein run karne dete hain, main UI thread ko block kiye bina. Yeh true parallelism provide karte hain aur heavy computations ke liye perfect hain.
Key Features:
• Separate thread mein run hote hain
• Main thread ko block nahi karte
• No DOM access (security reasons)
• Message passing through postMessage
• Can import other scripts
Complete Implementation:
Step 1: Create Worker File (worker.js):
// worker.js
self.addEventListener('message', (e) => {
const { type, data } = e.data;
switch(type) {
case 'HEAVY_CALCULATION':
const result = performHeavyCalculation(data);
self.postMessage({ type: 'RESULT', result });
break;
case 'PROCESS_DATA':
const processed = processLargeDataset(data);
self.postMessage({ type: 'PROCESSED', data: processed });
break;
}
});
function performHeavyCalculation(data) {
let sum = 0;
for (let i = 0; i < data.length; i++) {
sum += Math.sqrt(data[i]) * Math.sin(data[i]);
}
return sum;
}
function processLargeDataset(data) {
return data
.filter(item => item.active)
.map(item => ({
...item,
computed: item.value * 2
}))
.sort((a, b) => b.computed - a.computed);
}Step 2: Custom Hook for Worker:
// useWorker.js
import { useEffect, useRef, useState } from 'react';
const useWorker = (workerPath) => {
const workerRef = useRef(null);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
useEffect(() => {
// Create worker
workerRef.current = new Worker(workerPath);
// Listen for messages
workerRef.current.addEventListener('message', (e) => {
setResult(e.data);
setIsProcessing(false);
});
// Listen for errors
workerRef.current.addEventListener('error', (e) => {
setError(e.message);
setIsProcessing(false);
});
// Cleanup
return () => {
workerRef.current.terminate();
};
}, [workerPath]);
const postMessage = (message) => {
setIsProcessing(true);
setError(null);
workerRef.current.postMessage(message);
};
return { result, error, isProcessing, postMessage };
};Step 3: Use in Component:
const DataProcessor = () => {
const { result, isProcessing, postMessage } = useWorker('/worker.js');
const [data, setData] = useState([]);
const handleProcess = () => {
postMessage({
type: 'HEAVY_CALCULATION',
data: data
});
};
return (
<div>
<button onClick={handleProcess} disabled={isProcessing}>
{isProcessing ? 'Processing...' : 'Process Data'}
</button>
{result && <div>Result: {result.result}</div>}
</div>
);
};Alternative: Time Slicing (Without Workers):
const useTimeSlicing = (heavyTask, chunkSize = 1000) => {
const [result, setResult] = useState(null);
const [progress, setProgress] = useState(0);
const process = async (data) => {
let index = 0;
let accumulated = [];
while (index < data.length) {
const chunk = data.slice(index, index + chunkSize);
// Process chunk in next tick
const chunkResult = await new Promise(resolve => {
setTimeout(() => {
resolve(heavyTask(chunk));
}, 0);
});
accumulated.push(chunkResult);
index += chunkSize;
setProgress((index / data.length) * 100);
}
setResult(accumulated);
};
return { result, progress, process };
};requestIdleCallback Approach:
const processInIdle = (data, callback) => {
let index = 0;
let result = [];
const processChunk = (deadline) => {
while (deadline.timeRemaining() > 0 && index < data.length) {
result.push(heavyOperation(data[index]));
index++;
}
if (index < data.length) {
requestIdleCallback(processChunk);
} else {
callback(result);
}
};
requestIdleCallback(processChunk);
};Comparison:
| Technique | Pros | Cons |
|---|---|---|
| Web Workers | True parallelism, UI never blocks | No DOM access, setup overhead |
| Time Slicing | Simple, DOM access available | Slower overall, still on main thread |
| requestIdleCallback | Runs during idle time | Not guaranteed, browser support |
Best Practices:
✅ Use Workers for CPU-intensive tasks
✅ Keep worker code separate and focused
✅ Handle errors gracefully
✅ Terminate workers when done
✅ Consider worker pool for multiple tasks
✅ Measure performance before/after
Hard
Q7: Production-ready React app mein performance optimization ka complete strategy kya hoga? Monitoring aur best practices explain karo.
Answer:
Complete Performance Strategy:
Phase 1: Development (Build Time)
1. Code Splitting:
2. Bundle Analysis:
• webpack-bundle-analyzer use karo
• Large dependencies identify karo
• Tree-shaking verify karo
• Duplicate code eliminate karo
3. Component Optimization:
Phase 2: Runtime (User Experience)
1. Loading States:
2. Virtualization:
• Lists > 100 items ko virtualize karo
• react-window ya react-virtualized use karo
• Infinite scroll implement karo
3. Image Optimization:
Phase 3: Monitoring (Production)
1. Performance Metrics:
2. Error Tracking:
• Sentry for error monitoring
• LogRocket for session replay
• Custom error boundaries
3. Performance Budgets:
Phase 4: Continuous Optimization
Checklist:
☑️ Lighthouse score > 90
☑️ First Contentful Paint < 1.8s
☑️ Time to Interactive < 3.8s
☑️ Total bundle size < 200 KB (gzipped)
☑️ No unnecessary re-renders
☑️ Images optimized (WebP, lazy loading)
☑️ Code splitting implemented
☑️ Caching strategy in place
☑️ CDN for static assets
☑️ Service Worker for offline support
Tools:
• React DevTools Profiler
• Chrome DevTools Performance tab
• Lighthouse CI
• webpack-bundle-analyzer
• source-map-explorer
• Web Vitals library
Best Practices:
✅ Measure before optimizing
✅ Set performance budgets
✅ Automate performance testing
✅ Monitor real user metrics (RUM)
✅ Regular performance audits
✅ Document optimization decisions
✅ Train team on performance patterns
Complete Performance Strategy:
Phase 1: Development (Build Time)
1. Code Splitting:
// Route-based splitting
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
// Component-based splitting
const HeavyChart = lazy(() => import('./components/Chart'));
// Vendor splitting (webpack config)
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}2. Bundle Analysis:
• webpack-bundle-analyzer use karo
• Large dependencies identify karo
• Tree-shaking verify karo
• Duplicate code eliminate karo
3. Component Optimization:
// Memoization strategy
const ExpensiveList = React.memo(({ items }) => {
const sortedItems = useMemo(() =>
items.sort((a, b) => b.value - a.value),
[items]
);
const handleClick = useCallback((id) => {
// Handle click
}, []);
return sortedItems.map(item =>
<Item key={item.id} onClick={handleClick} />
);
});Phase 2: Runtime (User Experience)
1. Loading States:
// Suspense with fallback
<Suspense fallback={<LoadingSpinner />}>
<LazyComponent />
</Suspense>
// Progressive loading
const [isLoading, setIsLoading] = useState(true);
const [data, setData] = useState(null);
useEffect(() => {
// Show skeleton immediately
fetchData().then(result => {
setData(result);
setIsLoading(false);
});
}, []);2. Virtualization:
• Lists > 100 items ko virtualize karo
• react-window ya react-virtualized use karo
• Infinite scroll implement karo
3. Image Optimization:
// Lazy loading <img src="image.jpg" loading="lazy" /> // Responsive images <img srcSet="small.jpg 480w, medium.jpg 800w, large.jpg 1200w" sizes="(max-width: 600px) 480px, 800px" src="medium.jpg" /> // Progressive loading <ProgressiveImage placeholder="thumbnail.jpg" src="full-image.jpg" />
Phase 3: Monitoring (Production)
1. Performance Metrics:
// Core Web Vitals
import { getCLS, getFID, getLCP } from 'web-vitals';
getCLS(console.log); // Cumulative Layout Shift
getFID(console.log); // First Input Delay
getLCP(console.log); // Largest Contentful Paint
// Custom metrics
const onRenderCallback = (id, phase, actualDuration) => {
analytics.track('component_render', {
component: id,
phase: phase,
duration: actualDuration
});
};2. Error Tracking:
• Sentry for error monitoring
• LogRocket for session replay
• Custom error boundaries
3. Performance Budgets:
// webpack.config.js
performance: {
maxAssetSize: 250000, // 250 KB
maxEntrypointSize: 400000, // 400 KB
hints: 'error'
}Phase 4: Continuous Optimization
Checklist:
☑️ Lighthouse score > 90
☑️ First Contentful Paint < 1.8s
☑️ Time to Interactive < 3.8s
☑️ Total bundle size < 200 KB (gzipped)
☑️ No unnecessary re-renders
☑️ Images optimized (WebP, lazy loading)
☑️ Code splitting implemented
☑️ Caching strategy in place
☑️ CDN for static assets
☑️ Service Worker for offline support
Tools:
• React DevTools Profiler
• Chrome DevTools Performance tab
• Lighthouse CI
• webpack-bundle-analyzer
• source-map-explorer
• Web Vitals library
Best Practices:
✅ Measure before optimizing
✅ Set performance budgets
✅ Automate performance testing
✅ Monitor real user metrics (RUM)
✅ Regular performance audits
✅ Document optimization decisions
✅ Train team on performance patterns