Hello Developers!
If you're just starting with React, "Hooks" and "Lifecycle" can sound intimidating. But what if I told you that you already understand React? If you've ever managed a joint family, handled monthly expenses, or dealt with relatives, you're already a React pro.
Let's break down every React hook using the logic of a South Asian (Desi) household with simple, real examples.
The "Daily Essentials" (Core Hooks)
1. useState — Your Wallet (Jeb Kharch)
What it does: Remembers and updates a value in your component.
Desi Analogy: Your pocket money. You start with ₹500. When you buy samosas, the amount changes, and you need to remember the new balance.
Real Example:
import { useState } from 'react';
function WalletApp() {
const [balance, setBalance] = useState(500); // Start with ₹500
return (
<div>
<h2>Current Balance: ₹{balance}</h2>
<button onClick={() => setBalance(balance - 50)}>
Buy Samosas (₹50)
</button>
<button onClick={() => setBalance(balance + 100)}>
Mom gave money (₹100)
</button>
</div>
);
}
When to use: Anytime you need to remember and update a simple value (numbers, text, true/false).
2. useEffect — The Water Motor (Pani ki Tanki)
What it does: Runs code AFTER your component appears on screen. Used for side effects like fetching data, timers, or subscriptions.
Desi Analogy: You turn ON the water motor when you wake up. The tank fills automatically. But before you sleep, you must turn it OFF (cleanup), or water will overflow and waste!
Real Example:
import { useEffect, useState } from 'react';
function MotorApp() {
const [waterLevel, setWaterLevel] = useState(0);
useEffect(() => {
// Turn motor ON
console.log("Motor started!");
const motor = setInterval(() => {
setWaterLevel(prev => prev + 10);
}, 1000);
// Cleanup: Turn motor OFF when component disappears
return () => {
console.log("Motor stopped!");
clearInterval(motor);
};
}, []); // Empty array = Run only once when component appears
return <h2>Water Level: {waterLevel}%</h2>;
}
When to use: Fetching data from API, setting up timers, subscribing to events.
3. useContext — Family Values (Gharelu Sanskaar)
What it does: Shares data across many components without passing props manually through each level.
Desi Analogy: Family reputation and values. You don't teach each cousin individually how to behave with guests. Everyone just knows because "it's in the family culture." The values are shared automatically.
Real Example:
import { createContext, useContext, useState } from 'react';
// Create family values
const FamilyContext = createContext();
function GrandpaHouse() {
const [familyMotto] = useState("Respect elders, help others");
return (
<FamilyContext.Provider value={familyMotto}>
<Parent />
</FamilyContext.Provider>
);
}
function Parent() {
return <Child />;
}
function Child() {
// Child directly accesses family motto (no prop drilling!)
const motto = useContext(FamilyContext);
return <h3>Our family says: {motto}</h3>;
}
When to use: Sharing theme (dark/light mode), user info, language settings across many components.
The "Efficiency Experts" (Performance Hooks)
4. useMemo — Ginger-Garlic Paste (Adrak-Lehsan ka Paste)
What it does: Saves the result of an expensive calculation. Only recalculates when needed.
Desi Analogy: Grinding ginger-garlic paste is hard work. You do it once and store it in the fridge. You only re-grind when you buy fresh ginger or garlic. You don't grind it fresh every single time you cook!
Real Example:
import { useMemo, useState } from 'react';
function SpiceShop() {
const [ginger, setGinger] = useState("fresh");
const [garlic, setGarlic] = useState("fresh");
const [randomClicks, setRandomClicks] = useState(0);
// Heavy grinding operation
const paste = useMemo(() => {
console.log("Grinding paste...");
return `${ginger}-${garlic} paste ready!`;
}, [ginger, garlic]); // Only re-grind if ginger or garlic changes
return (
<div>
<h3>{paste}</h3>
<button onClick={() => setGinger("old")}>Ginger got old</button>
<button onClick={() => setRandomClicks(randomClicks + 1)}>
Random click (count: {randomClicks})
</button>
{/* Paste doesn't re-grind on random clicks! */}
</div>
);
}
When to use: Expensive calculations, filtering large lists, complex math operations.
5. useCallback — The Tea Recipe Muscle Memory
What it does: Saves the function itself so it doesn't get recreated on every render.
Desi Analogy: You memorized the exact way to pour tea with perfect foam. Once learned, your hands "remember" the movement. You don't re-learn the pouring technique every time a guest arrives—your muscle memory does it.
Real Example:
import { useCallback, useState } from 'react';
function ChaiShop() {
const [sugar, setSugar] = useState(2);
// Save the tea recipe (function won't be recreated unless sugar changes)
const makeTea = useCallback(() => {
console.log(`Making tea with ${sugar} spoons of sugar`);
}, [sugar]);
return (
<div>
<button onClick={makeTea}>Make Tea</button>
<button onClick={() => setSugar(sugar + 1)}>More Sugar</button>
<ExpensiveChild onMakeTea={makeTea} />
</div>
);
}
// This child won't re-render unnecessarily
function ExpensiveChild({ onMakeTea }) {
console.log("Child rendered");
return <button onClick={onMakeTea}>Guest wants tea</button>;
}
When to use: Passing functions to child components (especially with React.memo), preventing unnecessary re-renders.
The "Management" Hooks
6. useReducer — Grandfather's Account Register (Dada-ji ka Hisaab)
What it does: Manages complex state with clear rules and actions.
Desi Analogy: In a joint family, money is with Grandfather. You can't just take it. You tell him the ACTION ("I need money for milk"). He checks his RULES (reducer function), updates the register, and gives you the amount.
Real Example:
import { useReducer } from 'react';
// Grandfather's rules
function moneyReducer(currentMoney, action) {
switch(action.type) {
case 'BUY_MILK':
return currentMoney - 100;
case 'BUY_VEGETABLES':
return currentMoney - 200;
case 'MONTHLY_SALARY':
return currentMoney + 5000;
default:
return currentMoney;
}
}
function FamilyAccount() {
const [money, dispatch] = useReducer(moneyReducer, 10000); // Start with ₹10,000
return (
<div>
<h2>Family Money: ₹{money}</h2>
<button onClick={() => dispatch({type: 'BUY_MILK'})}>
Buy Milk (-₹100)
</button>
<button onClick={() => dispatch({type: 'BUY_VEGETABLES'})}>
Buy Vegetables (-₹200)
</button>
<button onClick={() => dispatch({type: 'MONTHLY_SALARY'})}>
Salary Day! (+₹5000)
</button>
</div>
);
}
When to use: Complex state with multiple related values, state that changes based on different actions.
7. useRef — The Junk Drawer (Kabaad ka Drawer)
What it does: Stores a value that persists but doesn't cause re-renders when changed. Also used to directly access DOM elements.
Desi Analogy: A drawer where you keep spare keys. You can change which key is in there anytime, but changing keys doesn't mean you repaint the whole house! It's just... there, waiting when needed.
Real Example 1 - Accessing DOM:
import { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const focusOnInput = () => {
// Directly grab the input element (like grabbing a key from drawer)
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} placeholder="Your name" />
<button onClick={focusOnInput}>Focus on Input</button>
</div>
);
}
Real Example 2 - Storing Values:
function Timer() {
const countRef = useRef(0);
const handleClick = () => {
countRef.current = countRef.current + 1;
console.log(`Clicked ${countRef.current} times`);
// Component doesn't re-render! Just silently remembers the count.
};
return <button onClick={handleClick}>Click me</button>;
}
When to use: Accessing input fields, storing timer IDs, keeping track of previous values without causing re-renders.
The Specialized Hooks
8. useId — Aadhaar Card for Components
What it does: Generates a unique ID for accessibility.
Desi Analogy: Every person needs a unique Aadhaar card so the government doesn't mix you up with your cousin who has the same name.
Real Example:
import { useId } from 'react';
function LoginForm() {
const emailId = useId();
const passwordId = useId();
return (
<form>
<label htmlFor={emailId}>Email:</label>
<input id={emailId} type="email" />
<label htmlFor={passwordId}>Password:</label>
<input id={passwordId} type="password" />
</form>
);
}
When to use: Connecting labels to inputs for accessibility.
9. useTransition — The Polite Host
What it does: Marks an update as non-urgent so UI stays responsive.
Desi Analogy: A guest arrives while you're doing laundry. You immediately greet them (urgent), but continue the laundry in the background (non-urgent). You're being a polite host—guest feels welcome, and laundry still gets done.
Real Example:
import { useTransition, useState } from 'react';
function SearchApp() {
const [input, setInput] = useState('');
const [list, setList] = useState([]);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
setInput(e.target.value); // Update immediately (urgent)
startTransition(() => {
// Heavy filtering (non-urgent, can wait)
const filtered = bigDataArray.filter(item =>
item.includes(e.target.value)
);
setList(filtered);
});
};
return (
<div>
<input value={input} onChange={handleChange} />
{isPending && <p>Searching...</p>}
<ul>{list.map(item => <li key={item}>{item}</li>)}</ul>
</div>
);
}
When to use: Heavy updates that shouldn't freeze the UI (searching, filtering large lists).
10. useDeferredValue — The Slow "Hanji, Aa Raha Hoon"
What it does: Shows an old value while the new one is loading.
Desi Analogy: Mom calls you. You reply "Coming!" immediately so she knows you heard. But you take a few seconds to actually finish your task and show up.
Real Example:
import { useDeferredValue, useState } from 'react';
function SearchWithDefer() {
const [input, setInput] = useState('');
const deferredInput = useDeferredValue(input);
return (
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<p>Current: {input}</p>
<p>Deferred: {deferredInput}</p>
<ExpensiveList query={deferredInput} />
</div>
);
}
When to use: Similar to useTransition, but you defer a value instead of a state update.
11. useSyncExternalStore — The Cricket Score Ticker
What it does: Syncs your React component with an external data source.
Desi Analogy: Cricket match is happening outside. You have a ticker in your house that updates live. Your house (component) stays in sync with the outside world (external store).
Real Example:
import { useSyncExternalStore } from 'react';
// External store (not React state)
let currentOnlineStatus = navigator.onLine;
let listeners = [];
const onlineStore = {
subscribe(callback) {
listeners.push(callback);
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
},
getSnapshot() {
return navigator.onLine;
}
};
function OnlineStatus() {
const isOnline = useSyncExternalStore(
onlineStore.subscribe,
onlineStore.getSnapshot
);
return <h2>{isOnline ? 'Online' : 'Offline'}</h2>;
}
When to use: Connecting to browser APIs, Redux stores, or other external data sources.
What's New in React 19?
React 19 introduces hooks that handle forms and loading states automatically.
12. useActionState — The Passport Office Status
What it does: Tracks form submission status (pending, error, success) automatically.
Desi Analogy: You submit documents at the passport office. You get three statuses: "Processing" (pending), "Rejected" (error), or "Approved" (success).
Real Example:
import { useActionState } from 'react';
async function submitForm(prevState, formData) {
const name = formData.get('name');
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
return { success: true, message: `Welcome ${name}!` };
}
function PassportForm() {
const [state, formAction, isPending] = useActionState(submitForm, null);
return (
<form action={formAction}>
<input name="name" placeholder="Your name" />
<button disabled={isPending}>
{isPending ? 'Processing...' : 'Submit'}
</button>
{state?.message && <p>{state.message}</p>}
</form>
);
}
When to use: Forms with loading states and server actions.
13. useOptimistic — Printing Wedding Cards Early
What it does: Shows success UI immediately while waiting for server confirmation.
Desi Analogy: Marriage is 99% fixed. You start printing wedding cards before the official stamp, because you're confident it'll happen. If it falls through (rare), you cancel the cards.
Real Example:
import { useOptimistic, useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, { id: Date.now(), text: newTodo, pending: true }]
);
const handleSubmit = async (e) => {
e.preventDefault();
const text = e.target.todo.value;
// Show immediately (optimistic)
addOptimisticTodo(text);
// Actually save to server
const saved = await saveTodoToServer(text);
setTodos([...todos, saved]);
};
return (
<form onSubmit={handleSubmit}>
<input name="todo" />
<button>Add</button>
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
{todo.text}
</li>
))}
</ul>
</form>
);
}
When to use: Improving UX by showing changes immediately (likes, comments, todo additions).
14. useFormStatus — The Kitchen Busy Light
What it does: A child component can check if the parent form is submitting.
Desi Analogy: The kitchen has a "busy" light. When the main stove (parent form) is on, the light tells everyone else to wait.
Real Example:
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button disabled={pending}>
{pending ? 'Saving...' : 'Save'}
</button>
);
}
function MyForm() {
return (
<form action={serverAction}>
<input name="title" />
<SubmitButton /> {/* Child knows parent form status */}
</form>
);
}
When to use: Disabling buttons or showing loaders based on parent form status.
15. use — Waiting for Mango Season
What it does: Suspends (pauses) the component until a Promise resolves.
Desi Analogy: You're waiting for mango season. You can't make mango pickle until the mangoes arrive. Your whole plan is on "pause" (suspended) until the promise (mangoes) is fulfilled.
Real Example:
import { use, Suspense } from 'react';
function MangoComponent({ mangoPromise }) {
const mangoes = use(mangoPromise); // Waits for promise
return <h2>Got {mangoes.length} mangoes!</h2>;
}
function App() {
const mangoPromise = fetch('/api/mangoes').then(r => r.json());
return (
<Suspense fallback={<p>Waiting for mango season...</p>}>
<MangoComponent mangoPromise={mangoPromise} />
</Suspense>
);
}
When to use: Reading promises or context inside components with Suspense.
📋 Quick Reference: When to Use Which Hook
| Your Need | Hook to Use | Think of It As |
|---|---|---|
| Remember a value | useState |
Your wallet |
| Run code after render | useEffect |
Water motor (with cleanup) |
| Share data globally | useContext |
Family values |
| Cache expensive calculation | useMemo |
Ginger-garlic paste |
| Cache a function | useCallback |
Tea-making muscle memory |
| Complex state logic | useReducer |
Grandfather's account book |
| Access DOM elements | useRef |
Junk drawer |
| Unique IDs | useId |
Aadhaar card |
| Non-urgent updates | useTransition |
Polite host |
| Defer a value | useDeferredValue |
"Coming!" response |
| External data sync | useSyncExternalStore |
Cricket ticker |
| Form status | useActionState |
Passport office |
| Optimistic UI | useOptimistic |
Early wedding cards |
| Check form status (child) | useFormStatus |
Kitchen busy light |
| Wait for data | use |
Mango season wait |
The Component Lifecycle in Desi Terms
| React Phase | Desi Meaning | What Happens |
|---|---|---|
| Mounting | Shuruvaat (Guest enters) | Component appears on screen |
| Updating | Guzaara (Daily life) | State/props change, component re-renders |
| Unmounting | Vidaayi (Guest leaves) | Component removed, cleanup happens |
Final Tips
-
Start simple: Begin with
useStateanduseEffect. Master these first. -
Don't optimize early: Only use
useMemoanduseCallbackwhen you have actual performance issues. - Read the errors: React's error messages are actually helpful—they'll tell you what's wrong.
- Practice: Build a todo app, a counter, a simple form. These cover 80% of real-world hooks.
Conclusion
React is just a digital version of managing a busy household. If you can manage family finances, handle the water motor, and remember where you kept the spare keys, you already understand Hooks!
Which hook do you find most confusing? Let's discuss in the comments!
Top comments (0)