DEV Community

Cover image for The Mall of React: An Uncle-Nephew Guide
surajrkhonde
surajrkhonde

Posted on

The Mall of React: An Uncle-Nephew Guide

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
Enter fullscreen mode Exit fullscreen mode

👦 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
Enter fullscreen mode Exit fullscreen mode

👦 Nephew: Walk me through the steps.

👨‍🦳 Uncle: Six of them:

  1. You write the floor plan — your component code.
  2. A studio mockup is built first — the Virtual DOM, invisible to shoppers.
  3. Something happens — a click, a purchase, a price update.
  4. A new mockup is built — reflecting what the shop should look like now.
  5. The renovation team compares old vs new mockupreconciliation; finding the differences is diffing.
  6. 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
Enter fullscreen mode Exit fullscreen mode

👦 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')
);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

👦 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
Enter fullscreen mode Exit fullscreen mode

👦 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);
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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 */ };
}, []);
Enter fullscreen mode Exit fullscreen mode

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>;
}
Enter fullscreen mode Exit fullscreen mode

👦 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 });
Enter fullscreen mode Exit fullscreen mode

👦 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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 />
  </>
);
Enter fullscreen mode Exit fullscreen mode

👦 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'));
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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]);
Enter fullscreen mode Exit fullscreen mode

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)} />
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 />}
Enter fullscreen mode Exit fullscreen mode

"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} />)}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Routes are sections of the mall:

<Routes>
  <Route path="/electronics" element={<Electronics />} />
  <Route path="/food-court" element={<FoodCourt />} />
  <Route path="/membership" element={<MembershipDesk />} />
</Routes>
Enter fullscreen mode Exit fullscreen mode

👦 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>
Enter fullscreen mode Exit fullscreen mode

👦 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>
} />
Enter fullscreen mode Exit fullscreen mode

👦 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
Enter fullscreen mode Exit fullscreen mode

👦 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)