Middleware: A function that sits between dispatching an action and the moment it reaches the reducer. It provides a third-party extension point between dispatching an action and the reducer receiving it, allowing you to intercept, modify, delay, or even stop actions.
Simple shabdon mein: Middleware ek "middleman" hai jo action aur reducer ke beech mein baithta hai. Jaise airport pe security check hota hai passengers ke liye, waise hi middleware har action ko check kar sakta hai, modify kar sakta hai, ya extra kaam kar sakta hai! 🛂
Real-world analogy: Socho aap ek letter bhej rahe ho. Post office (middleware) letter ko receive karta hai, stamp lagata hai, tracking add karta hai, aur phir deliver karta hai. Middleware bhi aise hi actions ke saath kaam karta hai!
🔄 Middleware Flow Visualization
🎬 Action
Dispatch
→
⚙️ Middleware 1
Logger
→
⚙️ Middleware 2
Thunk
→
⚙️ Middleware 3
Error Handler
→
📦 Reducer
State Update
// Middleware Signature (Curried Function)constmiddleware = (store) => (next) => (action) => {
// store: Redux store ka access// next: Agle middleware ya reducer ko call karne ke liye// action: Current action object// Before reducer
console.log('Action dispatched:', action);
// Call next middleware/reducerconst result = next(action);
// After reducer
console.log('New state:', store.getState());
return result;
};
1️⃣ Custom Middleware Banana
Custom Middleware: User-defined middleware functions that implement specific logic for handling actions, such as logging, analytics, crash reporting, or custom business logic.
Kyun banana? Redux mein built-in middleware limited hain. Aapko apne specific use cases ke liye custom middleware banana padta hai - jaise analytics tracking, API calls, validation, etc.
📝 Logger Middleware
Har action aur state change ko log karo
Debugging
🚨 Error Handler
Errors ko catch aur report karo
Error Tracking
📊 Analytics
User actions ko track karo
Monitoring
⏱️ Performance
Action execution time measure karo
Optimization
🎯 Live Demo: Custom Middleware in Action
Neeche buttons click karo aur dekho middleware kaise kaam karta hai!
Middleware ka order matter karta hai! Jo pehle apply hoga, wo pehle execute hoga. Logger ko usually sabse pehle rakhte hain taaki sab kuch log ho sake.
2️⃣ Redux Thunk - Deep Dive
Redux Thunk: A middleware that allows you to write action creators that return a function instead of an action object. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met.
Kya hai Thunk? Thunk ek function hai jo function return karta hai! 🤯 Normally action creators objects return karte hain, but thunk se aap functions return kar sakte ho jo async operations kar sakein.
Kyun chahiye? Redux mein reducers pure functions hone chahiye - no side effects, no async code. Thunk middleware se aap async operations (API calls, timers) kar sakte ho!
Use getState() sparingly - prefer passing data as arguments
3️⃣ Logging & Error Handling Middleware
Logging Middleware: Middleware that records actions, state changes, and other events for debugging and monitoring purposes. Error handling middleware catches and processes errors that occur during action processing.
Production mein kyun zaroori? Development mein toh console.log se kaam chal jata hai, but production mein proper logging aur error tracking chahiye. Jab user ko error aaye, aapko pata hona chahiye kya hua!
📊 Action Logging
Har action ko timestamp ke saath log karo
const logger = store => next => action => {
console.log('dispatching', action);
returnnext(action);
};
🚨 Error Tracking
Errors ko catch aur report karo
const errorHandler = store => next => action => {
try {
returnnext(action);
} catch (err) {
reportError(err);
}
};
⏱️ Performance Monitor
Slow actions ko identify karo
const perf = store => next => action => {
const start = Date.now();
const result = next(action);
console.log(Date.now() - start);
return result;
};
📈 State Diff
State changes ko visualize karo
const diff = store => next => action => {
const prev = store.getState();
const result = next(action);
const curr = store.getState();
console.log(diff(prev, curr));
return result;
};
Reselect: A library for creating memoized selector functions. Selectors can compute derived data, allowing Redux to store the minimal possible state while efficiently computing derived values on-demand.
Problem kya hai? Jab bhi state change hoti hai, sabhi connected components re-render hote hain. Agar aap complex calculations kar rahe ho (filtering, sorting, aggregating), toh ye calculations har render pe dobara hoti hain - bahut slow! 🐌
Solution: Reselect! Ye selectors ko "memoize" karta hai - matlab agar input same hai, toh cached result return karta hai. Calculation dobara nahi hoti! ⚡
❌ Without Memoization
Every render:
Filter array
Sort results
Calculate totals
Slow 🐌
✅ With Memoization
Only when input changes:
Check cache
Return cached result
No recalculation!
Fast ⚡
🎯 Live Demo: Reselect Performance
Dekho memoization se kitna performance improve hota hai!
0
Without Memo (ms)
0
With Memo (ms)
0
Performance Gain (%)
Execution Time Comparison
Without Memoization:
0ms
With Memoization:
0ms
// Reselect Basic Usageimport { createSelector } from'reselect';
// Input selectors - Simple functionsconstselectTodos = (state) => state.todos;
constselectFilter = (state) => state.filter;
// Memoized selector - Complex computationconst selectFilteredTodos = createSelector(
[selectTodos, selectFilter], // Input selectors
(todos, filter) => { // Result function
console.log('Computing filtered todos...');
switch (filter) {
case'COMPLETED':
return todos.filter(t => t.completed);
case'ACTIVE':
return todos.filter(t => !t.completed);
default:
return todos;
}
}
);
// Use in componentconst todos = useSelector(selectFilteredTodos);
// Agar todos aur filter same hain, cached result milega!
Reselect sirf last result cache karta hai. Agar aapko multiple results cache karne hain (different props ke liye), toh re-reselect library use karo jo LRU cache provide karti hai!
5️⃣ Middleware & Optimization Best Practices
1. ✅ Middleware Order
Sahi order mein apply karo
// Correct orderapplyMiddleware(
logger, // First
thunk, // Then
errorHandler // Last
)
const selectA = state => state.a;
const selectB = createSelector(
[selectA],
a => compute(a)
);
4. ✅ Avoid Over-Memoization
Simple selectors ko memoize mat karo
// ❌ Unnecessaryconst selectUser = createSelector(
state => state.user,
user => user
);
// ✅ Simple is betterconst selectUser = state => state.user;
🎯 Performance Optimization Checklist:
✅ Use Reselect for expensive computations
✅ Keep middleware lightweight
✅ Avoid synchronous heavy operations in middleware
✅ Use proper error boundaries
✅ Monitor middleware execution time
✅ Cache API responses when possible
✅ Debounce/throttle frequent actions
🎯 Interview Questions (Basic to Advanced)
Click on each question to reveal the answer
Q1. Redux Middleware kya hai aur kaise kaam karta hai? (Basic)
▼
Answer:
Middleware: Ek function jo action dispatch hone aur reducer tak pahunchne ke beech mein execute hota hai.
Signature:
const middleware = (store) => (next) => (action) => {
// Before reducer
console.log('Action:', action);
// Call next middleware/reducerconst result = next(action);
// After reducer
console.log('New State:', store.getState());
return result;
};
Kaise Kaam Karta Hai:
store: Redux store ka access (getState, dispatch)
next: Agle middleware ya reducer ko call karne ke liye
action: Current action object
Use Cases:
Logging (actions aur state changes)
Async operations (API calls)
Error handling
Analytics tracking
Action transformation
Hinglish: Middleware ek checkpoint hai jo har action ko check karta hai. Aap action ko modify kar sakte ho, delay kar sakte ho, ya extra kaam kar sakte ho before reducer!
Q2. Redux Thunk kya hai aur kab use karte hain? (Basic)
▼
Answer:
Redux Thunk: Ek middleware jo aapko action creators se functions return karne deta hai instead of plain objects.
Always call next(): Warna action reducer tak nahi pahunchega
Return result: next() ka result return karo
Order matters: Middleware order important hai
Access store: getState() aur dispatch() use kar sakte ho
Hinglish: Custom middleware banana easy hai - teen nested functions banao aur apna logic add karo. next() call karna mat bhoolna!
Q4. Reselect kya hai aur memoization kaise kaam karta hai? (Intermediate)
▼
Answer:
Reselect: Library for creating memoized selectors jo derived data efficiently compute karti hai.
Problem Without Memoization:
// Har render pe recalculate hota haiconstTodoList = () => {
const todos = useSelector(state => state.todos);
// Expensive computation - har render pe!const sortedTodos = todos
.filter(t => !t.completed)
.sort((a, b) => b.priority - a.priority);
return/* render */;
};
Solution With Reselect:
import { createSelector } from'reselect';
// Input selectorconstselectTodos = state => state.todos;
// Memoized selectorconst selectSortedActiveTodos = createSelector(
[selectTodos],
(todos) => {
console.log('Computing...'); // Sirf jab todos change horeturn todos
.filter(t => !t.completed)
.sort((a, b) => b.priority - a.priority);
}
);
// Use in componentconst sortedTodos = useSelector(selectSortedActiveTodos);
// Agar todos same hain, cached result milega!
How Memoization Works:
Selector ko call karo with current state
Input selectors run hote hain
Check: Kya inputs previous call se same hain?
If YES: Return cached result (fast!)
If NO: Run computation, cache result, return
Benefits:
Performance: Unnecessary recalculations avoid
Composable: Selectors ko chain kar sakte ho
Testable: Pure functions, easy to test
Encapsulation: State shape ko hide kar sakte ho
When to Use:
Filtering/sorting large arrays
Complex calculations
Aggregating data from multiple slices
Transforming data for UI
Hinglish: Reselect ek smart cache hai. Agar input same hai toh calculation dobara nahi hoti - cached result return hota hai. Bahut fast! ⚡
Q5. Middleware execution order kaise kaam karta hai? Example se explain karo (Advanced)
▼
Answer:
Middleware Chain: Middleware ek chain ki tarah execute hote hain - pehle se last tak, phir wapas last se pehle tak.
// Three middlewareconstmiddleware1 = store => next => action => {
console.log('1: Before');
const result = next(action);
console.log('1: After');
return result;
};
constmiddleware2 = store => next => action => {
console.log('2: Before');
const result = next(action);
console.log('2: After');
return result;
};
constmiddleware3 = store => next => action => {
console.log('3: Before');
const result = next(action);
console.log('3: After');
return result;
};
// Apply in orderapplyMiddleware(middleware1, middleware2, middleware3);
// When action is dispatched:// Output:// 1: Before// 2: Before// 3: Before// [Reducer executes]// 3: After// 2: After// 1: After
Execution Flow:
Action dispatch hota hai
Middleware 1 execute hota hai (before next)
Middleware 2 execute hota hai (before next)
Middleware 3 execute hota hai (before next)
Reducer execute hota hai
Middleware 3 complete hota hai (after next)
Middleware 2 complete hota hai (after next)
Middleware 1 complete hota hai (after next)
Practical Example:
// Correct order for common middlewareapplyMiddleware(
logger, // 1. Log everything first
crashReporter, // 2. Catch errors
thunk, // 3. Handle async actions
analytics // 4. Track after processing
);
// Why this order?// - Logger sees all actions (even from thunks)// - Crash reporter catches all errors// - Thunk converts functions to actions// - Analytics tracks final actions
Common Mistakes:
❌ Thunk after logger: Logger won't see thunk actions
❌ Error handler last: Won't catch errors from other middleware
❌ Not calling next(): Chain breaks, reducer never executes
Hinglish: Middleware ek onion ki tarah hai - bahar se andar jaate ho, phir andar se bahar aate ho. Order bahut important hai!
Problem: Agar aapko props ke basis pe selector banana hai (e.g., specific user ID), toh simple createSelector kaam nahi karega kyunki har component instance ko apna memoized selector chahiye.
Hinglish: Parametric selectors ke liye factory pattern use karo - har component instance ko apna memoized selector milega. Re-reselect library automatic LRU cache provide karti hai!
📝 Quick Summary
✅ Middleware: Action aur reducer ke beech ka layer