One mall. Many shops. From the day everything had to be rearranged by hand, to the smart, modern mall you shop in today.
Setting the Scene
👦 Nephew: Uncle, I use React every day, but if someone asks me how it actually works inside, I go blank.
👨🦳 Uncle: Then let's fix that with one picture in your head: a big shopping mall. Every React idea maps to something in this mall. Keep this table nearby.
| In the Mall | In React |
|---|---|
| The mall building | The web page, the browser |
| Mall Management | React itself |
| The floor plan / store layout instructions | Your code |
| Individual shops | Components |
| Merchandise Management supplies to a shop | Props |
| A shop's own private cash register & sales log | State |
| The actual shop windows customers see | The real DOM |
| The design studio's mockup display | The Virtual DOM |
| The renovation team comparing mockup to real window | Reconciliation / Diffing |
| Mall Security, prioritizing what needs attention now | The Scheduler / Fiber |
| Shoppers walking through the mall | The user |
| Shops that are built but not yet "open," waiting to be switched on | Hydration |
| The mall directory board + walking directions | The Router |
👦 Nephew: Alright, let's walk the mall.
Part 1: The Old, Exhausting Mall
👦 Nephew: Before React, how did people even manage websites?
👨🦳 Uncle: No design studio existed. Every tiny change — a shop rearranges one shelf, updates one price tag — meant someone walked out onto the actual, live shop floor, in front of real customers, and moved it by hand.
Change needed
│
v
Walk onto the LIVE shop floor
Adjust it directly, customers watching
👦 Nephew: Sounds slow for a big mall.
👨🦳 Uncle: It was — touching the real shop floor (the DOM) is expensive; every touch risks the whole storefront needing to redraw. So the mall hired a faster handyman crew: jQuery.
👦 Nephew: Problem solved?
👨🦳 Uncle: Faster hands, same job. Every single change still had to be manually planned and carried out, one at a time, live. Bigger mall, same tiring work.
Part 2: The Scale Problem That Forced a Fix
👦 Nephew: What actually broke this old way of working?
👨🦳 Uncle: Scale. Imagine a mall the size of Facebook's — not a hundred shoppers, but hundreds of millions, all inside at once. A "like" counter changes. A friend's online-status light turns green. A notification badge updates. Comments pour in live.
Each one of those is a live, walk-onto-the-floor change. Thousands per second, across millions of screens. The floor gets messy, staff bump into each other, updates lag.
So the engineers asked one question:
"What if, instead of touching the real shop floor every time, we first build the change in a private design studio, compare it to what's currently displayed, and only carry out the smallest necessary fix?"
That private studio is the Virtual DOM.
Part 3: The Design Studio — What the Virtual DOM Actually Does
BEFORE REACT WITH REACT (Virtual DOM)
───────────── ─────────────────────────
Change needed Change needed
│ │
v v
Walk onto the LIVE floor Build it in the DESIGN STUDIO
Fix it directly (customers don't see this)
(customers see every fumble) │
v
Compare studio mockup to
what's on the real floor NOW
│
v
Carry out ONLY the real
differences, on the real floor
👦 Nephew: Walk me through the steps.
👨🦳 Uncle: Six of them:
- You write the floor plan — your component code.
- A studio mockup is built first — the Virtual DOM, invisible to shoppers.
- Something happens — a click, a purchase, a price update.
- A new mockup is built — reflecting what the shop should look like now.
- The renovation team compares old vs new mockup — reconciliation; finding the differences is diffing.
- Only the real differences get carried out on the actual shop floor.
👦 Nephew: So the trick is: mock it up quietly first, then make the smallest real change.
👨🦳 Uncle: That's React's entire speed secret.
Part 4: Mall Security and the Smarter Priority System — Fiber
👦 Nephew: What's "React Fiber" and "Concurrent Rendering"?
👨🦳 Uncle: Meet Mall Security, whose job is deciding what needs attention right now.
In the old mall, once security starts handling one task — say, slowly walking a maintenance route — they can't stop halfway, even if something urgent happens elsewhere (a customer needs help immediately at checkout). The urgent thing waits until the whole maintenance route finishes.
👦 Nephew: Like typing in a search bar while product images are still loading, and your typing freezes?
👨🦳 Uncle: Exactly that. Old React handled updates one at a time, unable to interrupt itself for anything urgent.
OLD SECURITY NEW SECURITY (FIBER)
────────────── ──────────────────────
Follows one task start to finish Watches everything continuously
Cannot break away mid-task Notices urgent situations instantly
Urgent request must WAIT Switches attention immediately,
resumes the paused task later
👦 Nephew: So Fiber is a new priority rulebook.
👨🦳 Uncle: Exactly — pause low-priority work (background image loading), jump to urgent work (your typing), resume the paused work later. Fully automatic.
Part 5: The Instruction Translator — What JSX Really Is
👦 Nephew: Why do we write HTML-looking tags inside JavaScript?
👨🦳 Uncle: Because the mall's actual construction crew (the browser) doesn't understand your friendly floor-plan format directly. Something translates it first — that's Babel.
ReactDOM.render(
React.createElement('h1', null, 'Welcome!'),
document.getElementById('mall-entrance')
);
Since React 17, the translation got leaner — you don't need to import React into every file just to use JSX.
Three small translation rules: every tag must properly close, class becomes className, multi-word instructions get joined, like onClick.
Part 6: The Shops — Components
👦 Nephew: What exactly is a "component"?
👨🦳 Uncle: One shop. A reusable unit that displays part of the mall's overall layout. The whole mall is built by arranging many small shops into sections.
Mall
/ \
FoodCourt Electronics
/ \ / \
Counter1 Counter2 Phones Laptops
👦 Nephew: Can the same shop type appear more than once?
👨🦳 Uncle: Yes — two "Phones" branches in different wings run completely independently. One branch's register doesn't affect the other's.
Two styles of building a shop:
- Function components — the modern style, a plain function returning what to display.
- Class components — the older, more formal style, with more setup ceremony.
An even older style, React.createClass, is long deprecated. The mall keeps modernizing its own construction rules.
Part 7: Supplied Stock vs. the Shop's Own Register — Props and State
👦 Nephew: I always mix these up.
👨🦳 Uncle: Props are the stock Mall Management supplies to a shop. The shop displays and sells it, but can't change what was supplied — only Management restocks with something different.
State is the shop's own private register — today's sales count, whether the "sale" banner is currently on. The shop updates this itself, freely.
Management
│ (props flow down — supplied stock)
v
Shop
│ (messages flow up — via a request form Management gave them)
v
Management
👦 Nephew: Why can't information flow both ways freely?
👨🦳 Uncle: Then nobody could tell whether a display changed because a customer interacted with it, or because the stock itself changed. One-way flow keeps the whole mall predictable. And the strictest rule: a shop can never alter its own supplied stock. Try it, and Management just re-supplies the original at the next restock.
Part 8: Paperwork for the Older-Style Shops — Class Components
👦 Nephew: Class components have this ritual with this, bind, constructor.
👨🦳 Uncle: Formal opening-day paperwork, filed before the shop opens.
The constructor — the shop's registration form:
constructor(props) {
super(props);
this.state = { salesCount: 0 };
this.recordSale = this.recordSale.bind(this);
}
super(props) is how the shop formally acknowledges the supplied stock before using it on the form.
Binding — if a shop's "record a sale" instruction gets handed to a self-checkout kiosk to trigger, the shop's sense of "who am I" can get lost unless labeled beforehand. That labeling is bind.
Why setState isn't instant — React schedules updates and often batches several together, like the register updating its total after the current transaction finishes, not interrupting mid-sale for every scribble.
Part 9: A Shop's Full Life — Opening, Operating, Closing
OPENING DAY DAILY OPERATION CLOSING
(Mounting) (Updating) (Unmounting)
──────────── ────────────── ────────────
constructor shouldComponentUpdate componentWillUnmount
render render (cleanup: stop
componentDidMount componentDidUpdate deliveries, remove
sensors, lock up)
componentDidMount fires the moment the shop opens — safe to fetch initial stock data here. shouldComponentUpdate lets a shop say "that change doesn't affect my floor — skip re-arranging." componentWillUnmount fires right before closing — cancel pending deliveries, remove motion sensors, stop background music.
👦 Nephew: What if a shop forgets that cleanup?
👨🦳 Uncle: A ghost shop problem — a memory leak. The shop closed, but a background delivery subscription it started keeps running anyway, costing resources for a shop that no longer exists.
Part 10: Hooks — Giving Every Shop Standard Equipment
👦 Nephew: Why do hooks even exist?
👨🦳 Uncle: Function-style shops used to have no memory at all between visits — like a shop that forgets its own sales count the instant a customer leaves. Hooks gave them standard equipment, just like class-style shops always had.
useState — the register itself:
const [salesCount, setSalesCount] = useState(0);
You're not editing the old ledger page directly — setSalesCount requests a fresh page with the new total already written on it.
useEffect — a shop's standing instructions:
useEffect(() => { /* runs once, on opening */ }, []);
useEffect(() => { /* runs whenever salesCount changes */ }, [salesCount]);
useEffect(() => {
return () => { /* cleanup — runs on closing */ };
}, []);
useRef — a back-office drawer that doesn't trigger a storefront redraw when something's placed in it.
useMemo / useCallback — reusing yesterday's inventory count instead of recounting from scratch, when nothing's actually changed.
React.memo — telling a whole shop: "if your supplied stock hasn't changed, skip redecorating the window." The class-shop equivalent is React.PureComponent.
Part 11: A Shop's Own Routine — Custom Hooks
👦 Nephew: What if several shops need the exact same routine — like "track whether the mall's Wi-Fi is currently online"?
👨🦳 Uncle: One shop writes that routine once, and any other shop borrows a copy. That's a custom hook.
function useWifiStatus() {
const [online, setOnline] = useState(navigator.onLine);
useEffect(() => {
const update = () => setOnline(navigator.onLine);
window.addEventListener('online', update);
window.addEventListener('offline', update);
return () => {
window.removeEventListener('online', update);
window.removeEventListener('offline', update);
};
}, []);
return online;
}
function PaymentCounter() {
const online = useWifiStatus();
return <p>{online ? 'Card payments available' : 'Cash only right now'}</p>;
}
👦 Nephew: So it's just organizing existing hooks under one name?
👨🦳 Uncle: Exactly — no new magic, just a reusable routine any shop can adopt.
Part 12: A Formal Ledger for Complicated Sales — useReducer
👦 Nephew: What if a shop's register has many related fields, and updates depend on each other in complex ways?
👨🦳 Uncle: Switch to a formal ledger system — useReducer. Instead of writing directly, the shop submits a formal request ("action") to a strict accountant (the "reducer"), who decides exactly how the ledger updates.
function reducer(state, action) {
switch (action.type) {
case 'sale': return { total: state.total + action.amount };
case 'refund': return { total: state.total - action.amount };
default: return state;
}
}
const [ledger, dispatch] = useReducer(reducer, { total: 0 });
dispatch({ type: 'sale', amount: 500 });
👦 Nephew: Sounds like Redux, but for one shop.
👨🦳 Uncle: Exactly right — useReducer is Redux's core idea, scaled to a single shop's own ledger.
Part 13: When a Shop Has a Crisis — Error Boundaries
👦 Nephew: What if a shop has a total system failure — say, its checkout software crashes?
👨🦳 Uncle: Without protection, the entire mall shuts down — one shop's failure takes down everything. Real malls don't work that way.
An Error Boundary is a fire door around a section — if a shop inside collapses, the boundary catches it, displays "this section is temporarily unavailable," and the rest of the mall keeps operating normally.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
render() {
if (this.state.hasError) return <p>This section is temporarily closed.</p>;
return this.props.children;
}
}
<ErrorBoundary>
<RiskyShop />
</ErrorBoundary>
Part 14: "Back in 5 Minutes" — Suspense and Lazy Loading
👦 Nephew: What if a shop isn't ready yet — still being fitted out?
👨🦳 Uncle: Show a "back in 5 minutes" sign instead of an empty gap. That's Suspense.
const LuxuryStore = React.lazy(() => import('./LuxuryStore'));
<Suspense fallback={<p>This store is opening shortly...</p>}>
<LuxuryStore />
</Suspense>
React.lazy means: don't build and fit out a shop's entire interior until a shopper actually walks toward that section. If your mall has fifty stores, why make every visitor wait for all fifty to be fully constructed before the doors even open?
WITHOUT lazy loading WITH lazy loading
───────────────────── ──────────────────
Build ALL 50 shops Build only the shops needed
before opening the doors for the entrance area
↓ ↓
Slow grand opening Fast opening — other shops
built only as shoppers approach
Part 15: Invisible Groupings and Shops That Appear Elsewhere — Fragments and Portals
👦 Nephew: Sometimes I need to return two shops from one section, but React wants a single wrapper.
👨🦳 Uncle: Use a Fragment — an invisible grouping with no extra physical structure added.
return (
<>
<ShopOne />
<ShopTwo />
</>
);
👦 Nephew: And something like a popup announcement that appears floating over the whole mall?
👨🦳 Uncle: That's a Portal — logically still part of your section (still gets its supplied stock and register access normally), but physically displayed somewhere else entirely, like a mall-wide announcement screen built specifically for overlays.
ReactDOM.createPortal(<AnnouncementModal />, document.getElementById('modal-root'));
Part 16: The Opening-Day Inspector — StrictMode
👦 Nephew: What does <React.StrictMode> do?
👨🦳 Uncle: An inspector who deliberately makes shops run their opening routine twice, during development only — specifically to catch shops that accidentally rely on leftover setup from the first run instead of starting cleanly each time. It never runs these extra checks in the live, real mall — only during rehearsal.
Part 17: The Sticky Note in the Drawer — Stale Closures
👦 Nephew: My useEffect keeps using an old value, even after it clearly changed. What's happening?
👨🦳 Uncle: A stale closure. A shop writes a sticky note at the start of a routine and keeps referring back to that same note all day — even if the real number has changed since.
useEffect(() => {
const interval = setInterval(() => {
console.log(salesCount); // frozen at whatever it was when this ran
}, 1000);
return () => clearInterval(interval);
}, []); // empty array = write the note once, never refresh it
Fix: tell the routine to write a fresh note whenever the real value changes.
useEffect(() => {
const interval = setInterval(() => {
console.log(salesCount); // always fresh now
}, 1000);
return () => clearInterval(interval);
}, [salesCount]);
Part 18: The Checkout Counter — Controlled and Uncontrolled Forms
👦 Nephew: Forms confuse me most.
👨🦳 Uncle: Picture a checkout counter.
Controlled — Management watches and records every single item scanned, live, the instant it happens:
<input value={value} onChange={(e) => setValue(e.target.value)} />
Uncontrolled — the cashier keeps their own running total, and Management only checks the final receipt at the end:
const inputRef = useRef();
<input ref={inputRef} defaultValue="" />
// Management checks inputRef.current.value only at submit
Controlled is more common — Management usually wants instant feedback, like flagging an invalid coupon code as it's typed.
Part 19: Deciding What's Displayed — Conditionals and Lists
{isMember ? <VIPLounge /> : <PublicWaitingArea />}
"If true, display this; otherwise, display that."
For a whole row of similar shops (a food court, say), use .map(), but every item needs a key — a shop number pinned to each unit, so the renovation team knows exactly which one moved, was added, or removed.
{stalls.map(stall => <FoodStall key={stall.id} data={stall} />)}
Part 20: Before the Doors Open — How the Page Actually Loads
1. Blueprint arrives → raw HTML reaches the browser
2. Interior design applied → CSS applied, layout and colors appear
3. Staff/equipment arrives → JavaScript (React) downloads
4. Mockup built → React builds its Virtual DOM
5. Doors open → React places everything on the real floor
6. (if applicable)
Frozen displays wake up → Hydration
If shops arrive already fully built and stocked before doors open — Server-Side Rendering — shoppers see a complete mall immediately. But those shops are frozen displays until React "wakes them up," attaching working registers and staff. That's Hydration.
If instead the mall opens as an empty shell, waiting for construction crews to arrive before building anything — Client-Side Rendering — shoppers initially see nothing.
Either way, shoppers only ever experience plain floors, plain lighting, plain signage. In web terms: the browser only ever receives plain HTML, CSS, JavaScript. JSX, hooks, components are just a better-organized way for you to produce that final result.
Part 21: The City Guide Listing — Why Next.js Matters for Being Found
👦 Nephew: Why do people add Next.js on top of React?
👨🦳 Uncle: Imagine a city guide inspector visits your mall before construction finishes. The shell is empty. They walk away and list your mall as "nothing here."
That's what a search engine's crawler does to pure Client-Side Rendering — visits, sees an empty shell, reports "empty page." Next.js fixes this by ensuring the mall is already built before anyone peeks in:
- Server-Side Rendering — build it fresh, for every visitor, on request, or
- Static Site Generation — build it once, ahead of time, and hand out a ready photograph instantly.
Either way, the inspector always sees a fully built, meaningful mall.
Part 22: Mall-Wide Communication — Context, Redux, React Query
👦 Nephew: What about Redux, Context, React Query?
👨🦳 Uncle: Picture the mall grown huge — many floors, fifty shops, information that needs to travel between shops that aren't near each other. Passing a message shop-to-shop through everyone in between gets messy fast. That's "prop drilling."
- Context — a mall-wide PA announcement system. Any shop tunes in directly. Good for things that rarely change, like "which membership tier is currently browsing."
- Redux — a proper Central Management Office. All important information lives in one official ledger. Shops don't edit it directly — they submit a formal request ("action"), and a strict rulebook ("reducer") decides how it updates.
- React Query — a dedicated logistics team whose only job is talking to outside suppliers (an external API). Fetches, remembers recent orders so it doesn't ask twice unnecessarily, quietly refreshes stock in the background.
👦 Nephew: If one small thing changes, does the whole mall rebuild?
👨🦳 Uncle: No — only the shop whose register or supplied stock actually changed, plus anything directly depending on it. Keep registers as local as possible, use React.memo generously, split PA channels by topic instead of one giant announcement for everything.
Part 23: Getting Around the Mall — Routing
👦 Nephew: How do multiple pages actually work in a React app?
👨🦳 Uncle: This is where the mall shines as a picture. A single-page app is really a mall with one shared floor structure — entrance, corridors, PA system — and different sections slide into view depending on where the directory board points you.
Mall Directory Board (Router)
/ | \
/electronics /food-court /membership
│ │ │
Electronics FoodCourt MembershipDesk
Section Section (protected)
Routes are sections of the mall:
<Routes>
<Route path="/electronics" element={<Electronics />} />
<Route path="/food-court" element={<FoodCourt />} />
<Route path="/membership" element={<MembershipDesk />} />
</Routes>
👦 Nephew: What about a department store that has its own smaller sections inside it — like Electronics has a Phones sub-section and a Laptops sub-section?
👨🦳 Uncle: Nested routes — the outer shop (Electronics) keeps its own shared shelving and signage (a layout), while only the inner sub-section changes as you walk around inside it.
<Route path="/electronics" element={<ElectronicsLayout />}>
<Route path="phones" element={<Phones />} />
<Route path="laptops" element={<Laptops />} />
</Route>
👦 Nephew: And the Membership Desk — that needs a card to even enter?
👨🦳 Uncle: A protected route — a checkpoint before the section, checking for a valid membership card (an auth token) before letting the visitor walk in. No card, redirect them to the sign-up counter instead.
function ProtectedRoute({ children }) {
const isMember = useAuth();
if (!isMember) return <Navigate to="/join" />;
return children;
}
<Route path="/membership" element={
<ProtectedRoute><MembershipDesk /></ProtectedRoute>
} />
👦 Nephew: So the directory board (router) decides which section to render, nested routes are stores-within-stores, and protected routes are checkpoints?
👨🦳 Uncle: Exactly the whole picture — and notice it's the same mall the whole time. No page reload, no new building. The router just swaps which section is currently visible, reusing the shared corridors and PA system underneath.
Part 24: Putting the Whole Mall Together
1. Blueprint translated (Babel), bundled — some sections maybe pre-built (Next.js)
2. Visitor arrives — sees an already-built mall (SSR/SSG) or an empty shell (CSR)
3. Doors visually open — HTML/CSS paint immediately
4. Displays wake up — Hydration attaches interactivity
5. Shopper walks around — Security (Fiber) prioritizes what needs attention
6. The directory board routes them to a section (Router)
7. A change happens — mockup built, diffed, only real changes reach the floor
8. A shop eventually closes — cleanup runs, nothing left running needlessly
👦 Nephew: So React isn't magic — it's an extremely well-organized construction, priority, and navigation system.
👨🦳 Uncle: Exactly. The day you can explain why each piece exists — not just name it — is the day you've actually understood React.
Quick Reference — Uncle's Cheat Sheet
| Idea | In one line |
|---|---|
| Virtual DOM | A private design-studio mockup, checked before touching the real floor |
| Reconciliation / Diffing | Comparing old and new mockups to find what changed |
| React Fiber | Smarter Mall Security — can pause and reprioritize |
| Concurrent Rendering | Letting urgent shopper needs jump ahead of background work |
| JSX | Friendly floor-plan format, translated by Babel |
| Props | Stock Management supplies to a shop (read-only) |
| State | A shop's own private, changeable register |
useState |
Gives a function-shop a register |
useEffect |
Opening, updating, and closing instructions |
useRef |
A back-office drawer that doesn't trigger a redraw |
useMemo / useCallback
|
Reusing yesterday's count instead of recounting |
React.memo |
"Skip redecorating if supplied stock hasn't changed" |
| Custom Hook | A reusable routine any shop can borrow |
useReducer |
A formal accountant deciding ledger updates |
| Error Boundary | A fire door — contains a crisis to one section |
Suspense / React.lazy
|
"Back in 5 minutes" sign; build shops only when needed |
| Fragment | An invisible grouping, no extra structure |
| Portal | A shop rendering physically elsewhere, logically still in the tree |
| StrictMode | An inspector forcing double-runs to catch bugs early |
| Stale closure | An old sticky note, never refreshed |
| Controlled input | Management watches and records live |
| Uncontrolled input | Cashier keeps their own running total, checked at the end |
| Hydration | Waking up already-built, frozen displays |
| SSR | Building fresh, for every visitor |
| SSG | Building once, reusing the photograph |
| Redux | A central management office, one official ledger |
| Context | A mall-wide PA announcement system |
| React Query | The logistics team talking to outside suppliers |
| Router | The directory board deciding which section shows |
| Nested Routes | Stores-within-stores, sharing an outer layout |
| Protected Routes | A checkpoint requiring a membership card |
"Less noise, more action." For each idea, be able to say out loud what real problem it solves — that's worth more than memorizing hook names.
Top comments (0)