A tiffin menu, a smart cook, and a thali where only the one sabzi that changed gets refilled.
The full React mental model for interviews — in simple language with desi examples. Components, props, state, hooks, lifecycle, the Virtual DOM, reconciliation, CSR vs SSR vs SSG, and what changes when there's no DOM at all (React Native). Each concept has a one-line technical definition too.
The one story to remember
Think of a tiffin service. You don't cook every item yourself — you give the cook a menu card that says what today's thali should have (your components describe what the screen should look like). Now a customer says "make the dal less spicy" — one small change (state). The cook doesn't throw away the whole thali and start fresh. He looks at the old thali and the new menu, notices only the dal is different (the Virtual DOM diff / reconciliation), and refills just that one bowl (the real DOM update). That's React's whole job: you say what you want on the plate, React figures out the least work to make it happen. React Native is the same cook — but he serves on a steel thali (native iOS/Android views) instead of a paper plate (the browser DOM).
1You write components that return UI (JSX) "the blueprint"
↓
2State or props change setState / new prop / context update
↓
3React re-runs the component → new Virtual DOM tree a fresh blueprint, in memory
↓
4Diff new tree vs old tree reconciliation — find what actually changed
↓
5Commit only the differences to the real DOM / native views the minimal repaint
01
What React is — you say the "what", not the "how"
Technical definitionReact is a JavaScript library for building user interfaces using a declarative, component-based model.
In plain words: React lets you build screens out of small reusable pieces, and you just describe what each piece should look like. You don't write the long list of steps to update the screen — React does that for you. The old way (writing every step yourself) is called imperative; React's way is declarative.
// Imperative — you do every step by handconst el = document.getElementById("count");
el.textContent = count; // find the box, change it yourself// Declarative (React) — you just say the resultreturn <span>{count}</span>; // React updates the screen for you
Desi example
Imperative is cooking the whole meal yourself, step by step. Declarative is ordering on Swiggy — you say "one paneer butter masala," and how it gets made is someone else's problem. You describe the result; React handles the kitchen.
React is declarative: UI = f(state) — the screen is just a picture of your current data. You describe the result; React figures out how to get there. That one idea is the whole philosophy.
02
JSX — HTML-looking code that is actually JavaScript
Technical definitionJSX is a syntax extension that lets you write HTML-like markup in JavaScript; it compiles to React.createElement() calls that return plain objects.
It looks like HTML, but it's not — a build tool (Babel) quietly turns every tag into a normal JavaScript function call. So the HTML you "write" is really just JavaScript objects underneath.
// what you writeconst x = <h1 className="title">Hi</h1>;
// what it secretly becomesconst x = React.createElement("h1", { className: "title" }, "Hi");
Because it's really JavaScript, you write className instead of class, and onClick in camelCase — these are object keys, not HTML attributes. Put any JS value inside { }, and remember a component must return one outer tag (wrap siblings in <>…</>).
Desi example
JSX is like writing your address in English letters but it's really Hindi — looks like one thing, means another. The "HTML" you see is just JavaScript wearing a familiar kurta.
JSX is not HTML — it turns into React.createElement calls that return objects. It's just a comfortable way to write your UI.
03
Components, props & state
Technical definition
A component is a reusable function that returns UI. Props are read-only inputs passed from a parent; state is private data a component owns and can change over time.
A component is just a function that returns some screen. Two kinds of data go into it — and the difference between them is a favourite interview question.
Props
Inputs passed in from the parent. Read-only inside the component. Data flows one way: parent → child.
State
Data the component owns and can change over time. Changing it (via setState) triggers a re-render.
props come from above · state lives within · both, when they change, cause a re-render
functionGreeting({ name }) { // name = a propconst [count, setCount] = useState(0); // count = statereturn <button onClick={() => setCount(count + 1)}>
{name} clicked {count}
</button>;
}
Desi exampleProps are like the pocket money your parents give you — it comes from above and you can't change the amount, only use it. State is the cash in your own wallet — yours to spend and refill as you like. When either changes, you re-plan your day (re-render).
One-way data flow
Data flows downward through props — parent to child, like instructions from elders to younger ones. A child can't directly change a prop. To change the parent's data, the parent hands down a function and the child calls it. This top-down flow is exactly why React apps are easy to follow.
Props = read-only, comes from the parent. State = the component's own, changeable data. Change either one and React re-draws that part. Data always flows one way: top to bottom.
04
Hooks — giving powers to simple functions
Technical definitionHooks are functions that let function components use state, lifecycle, and other React features without writing a class.
Earlier, only big "class" components could hold state. Hooks let simple function components do everything — hold data, fetch from APIs, and clean up after themselves. The ones you'll use daily:
useStatelocal state; returns the value and a setter that triggers a re-render.
useEffectrun side effects (fetch, subscriptions, timers) after render; the dependency array controls when.
useContextread shared data from a Context without prop-drilling.
useRefa mutable box that persists across renders without causing one (DOM refs, instance values).
useMemo / useCallbackcache a computed value / a function identity between renders to avoid wasted work.
// useEffect — the dependency array is everythinguseEffect(() => {
fetchUser(id);
return () => cleanup(); // cleanup runs before re-run / on unmount
}, [id]); // re-run only when id changes// [] = run once · no array = run after EVERY render
Desi exampleuseEffect's dependency array is like telling your maid when to come. [] = come only on day one. [salary] = come whenever salary changes. No array = come every single time something happens — usually a mistake.
The rules of hooks
Always call hooks at the top of your component — never inside an if, a loop, or a nested function. React remembers your state by the order hooks are called, so the order must be the same every render.
Hooks give functions memory and lifecycle. The key skill is useEffect's dependency array: [] = run once, [x] = run when x changes, nothing = run every render. The returned cleanup function stops leaks (old timers, old listeners).
05
The component lifecycle — birth, growth, goodbye
Technical definition
The component lifecycle is the set of phases a component goes through — mounting, updating, and unmounting.
Every component has a life, just like a guest at a function: they arrive, they stay and react to things, and finally they leave. Three phases — and a common question is matching the old class methods to the new hook way.
Desi example
A wedding guest: mount = they arrive and you greet them. update = they react as events change — eat, dance, take photos. unmount = they leave, and you clear their plate and chair (cleanup).
Mount
Component is created and inserted. Class: constructor → render → componentDidMount. Hook: first render + useEffect([]).
Removed from the screen. Class: componentWillUnmount. Hook: the function returned from useEffect.
Class method
Hook equivalent
When
componentDidMount
useEffect(fn, [])
once, after first render — fetch initial data
componentDidUpdate
useEffect(fn, [deps])
after renders where a dep changed
componentWillUnmount
return () => {} in useEffect
cleanup before removal — unsubscribe, clear timers
Three phases: mount → update → unmount. In hooks, all three live inside useEffect: the body handles mount/update, the returned function handles cleanup/unmount.
06
The DOM vs the Virtual DOM
Technical definition
The DOM is the browser's live tree of the page. The Virtual DOM is a lightweight in-memory copy of it that React diffs before updating the real DOM.
The real DOM is the actual page the browser shows. Changing it directly is slow — every small change can make the browser re-measure and repaint things. So React keeps a fast copy in memory (the Virtual DOM), makes changes there first, and only then touches the real page — as little as possible.
Desi example
The real DOM is the final answer sheet in an exam — messy to keep cutting and rewriting. The Virtual DOM is your rough sheet: do all your working there, and copy only the clean final answer onto the real sheet. Less cutting, less mess.
So when your data changes, React makes a new rough copy, compares it with the old one, and works out the smallest change needed. You can happily think "redraw everything" while React quietly changes almost nothing on screen.
The real DOM is slow to change. The Virtual DOM is a fast memory copy React compares first, so it touches the real page only where something actually changed.
07
Reconciliation & why keys matter
Technical definitionReconciliation is React's diffing process that compares the new and old trees to find the minimal changes. A key is a stable id that lets React match list items across renders.
Reconciliation is just React comparing "before" and "after" and deciding what to add, change, or remove. To stay fast it follows simple rules: same type of element → update it where it is; different type → throw it out and build fresh.
For lists, React needs a key — a unique id on each item — to know which one is which. Without proper keys, when the list reorders React gets confused about which item moved and which is new.
// ✅ stable, unique key from the data
{users.map(u => <Row key={u.id} user={u} />)}
// ❌ index as key — breaks on reorder/insert/delete
{users.map((u, i) => <Row key={i} user={u} />)}
Desi example
Keys are like roll numbers in a class. If you identify students by "1st bench, 2nd bench" (the index) and the seating changes, you'll mark the wrong student present. Give each a fixed roll number (a stable id) and they're always recognised, wherever they sit.
The index-key bug
Using the array index as the key looks fine — until you reorder or delete from the middle. Then React reuses the wrong row, and typed text or animations jump to the wrong item. Always use a stable id.
Reconciliation = the comparison. Keys = roll numbers that let React recognise list items. Use a stable, unique id — never the array index for lists that change.
08
Rendering: CSR vs SSR vs SSG (and hydration)
Technical definitionCSR builds the HTML in the browser; SSR builds it on the server per request; SSG builds it once at build time. Hydration is React attaching interactivity to server-sent HTML.
This is just a question of where and when the page gets made — a favourite Next.js interview topic. Four options:
Strategy
HTML built…
Trade-off
CSR — Client-Side Rendering
in the browser, after JS loads
Plain React SPA. Fast navigation once loaded, but a blank page until JS runs → slower first paint & weaker SEO.
SSR — Server-Side Rendering
on the server, per request
Full HTML on first load → fast first paint, good SEO. Costs server work on every request. (Next.js dynamic pages.)
SSG — Static Site Generation
at build time, once
Pre-rendered HTML served from a CDN → fastest + cheapest. Best for content that rarely changes. (Next.js static pages.)
ISR — Incremental Static Regen
at build, then re-built on a timer
SSG that refreshes in the background → static speed with periodically fresh data.
Desi example
Think of ordering food. CSR = the restaurant starts cooking only after you sit down — you wait at an empty table. SSR = they cook a fresh plate the moment your order comes, every time. SSG = it's a buffet, cooked in the morning and ready to serve instantly all day.
Hydration joins the two worlds: the server sends a finished, good-looking page (so it appears instantly), then React loads in the browser and "wakes it up" — wiring buttons and clicks so it actually works. The server serves the photo; hydration makes it a real, clickable meal.
CSR = browser makes it (empty, then fast). SSR = server makes it per visit (fast first view + good for Google). SSG = made once at build time (fastest). Hydration = React switching on the interactivity of a server-made page.
09
Context & avoiding prop-drilling
Technical definitionContext shares a value with every component in a subtree without passing props down by hand. Prop-drilling is passing a prop through many layers just to reach a deep child.
Sometimes a deep-down component needs data that lives way up top — like the logged-in user or the app theme. Passing it hand-to-hand through five components in between is called prop-drilling, and it's painful. Context fixes this: put the value at the top, and any component below can grab it directly.
Desi example
Prop-drilling is passing the TV remote person-to-person across the whole family to reach dadaji in the corner. Context is mounting the AC on the wall — everyone in the room feels it directly, no passing required.
const ThemeCtx = React.createContext("light");
<ThemeCtx.Provider value="dark">
<App /> // any child can read it
</ThemeCtx.Provider>
const theme = useContext(ThemeCtx); // no drilling
Context isn't a state manager
Every consumer re-renders when the context value changes. For large, frequently-updating global state, reach for a dedicated store (Redux Toolkit, Zustand). Context shines for low-frequency, widely-read values.
Context removes prop-drilling for widely-shared, rarely-changing values. It's not a performance-tuned state manager — heavy global state belongs in Redux/Zustand.
10
Performance: memo, useMemo, useCallback
Technical definitionReact.memo skips re-rendering a component if its props didn't change. useMemo caches a computed value; useCallback caches a function's identity — both across renders.
By default, when a parent re-renders, its children re-render too. Usually that's totally fine — the Virtual DOM comparison is cheap. But when something is genuinely heavy, these three tools let React skip repeating work it already did.
Desi example
It's like meal-prep: useMemo is grinding the masala once on Sunday and reusing it all week instead of grinding fresh every meal. React.memo is "the dish hasn't changed, don't re-cook it." You only bother for dishes that are actually slow to make.
React.memowraps a component so it re-renders only when its props actually change.
useMemocaches the result of an expensive calculation between renders.
useCallbackcaches a function's identity so memoized children don't see a "new" prop each render.
Don't over-optimize
Memoization isn't free — it costs memory and comparison work. Profile first. Wrapping everything in useMemo/useCallback by reflex often makes code slower and harder to read. Optimize the proven hot path, not every component.
React.memo skips a component, useMemo caches a value, useCallback caches a function. Measure before reaching for them — premature memoization is its own bug.
★ THE FULL PICTURE
One render, start to screen
This is the entire pipeline on one page. A state change at the top flows down through diffing and lands as a minimal update on the real DOM (web) or native views (mobile). Memorize this shape and you can rebuild every answer from it.
Componenta function that takes props + state and returns UI (the blueprint).
Virtual DOMan in-memory tree of elements React diffs before touching the screen.
Reconciliationthe diff that finds the minimal set of real changes.
Rendererreact-dom (web) or react-native (mobile) — applies the diff to the real target.
Hydrationattaching React's interactivity to server-rendered HTML.
Read it as a sentence: state changes → React re-runs the component to make a new Virtual DOM → it diffs that against the old tree (reconciliation, lists matched by key) → and commits only the differences to the real DOM on web or native views on mobile. That single sentence is the entire model.
If you can draw change → render → diff → commit and say "the diffing core is shared; only the renderer differs between web and native," you can answer almost any React fundamentals question on the spot.
11
React Native — same React, no DOM
Technical definitionReact Native uses the same React core but renders to native iOS/Android views instead of the DOM, communicating with native code via the bridge (old) or JSI/Fabric (new).
Here's the good news for interviews: React Native is the same React you already know — same components, props, state, hooks, Virtual DOM, reconciliation. Only two things change: what you build with (the building blocks) and what it draws on (the screen). No HTML, no CSS files, no browser DOM.
Web (React)
Mobile (React Native)
Note
<div> / <span>
<View> / <Text>
native primitives, not HTML tags
<img>
<Image>
all text MUST be inside <Text>
CSS / className
StyleSheet (JS objects)
camelCase, Flexbox by default, no cascade
onClick
onPress + Pressable
touch, not click
react-dom
react-native
the renderer that maps elements to real views
Under the hood, RN runs your JS and talks to real iOS/Android UI. The old architecture used an async bridge to pass serialized messages between JS and native; the new architecture (Fabric + JSI) lets JS call native synchronously, removing that bottleneck.
Desi example
Same cook, same recipe — but he serves on a steel thali (native iOS/Android views) instead of a paper plate (the browser). The cooking doesn't change; only the plate does. That's why your React skills carry straight over to mobile.
React Native = same React core, different renderer. View/Text/Image instead of HTML, StyleSheet instead of CSS, onPress instead of onClick. JS ↔ native talk via the bridge (old) or JSI/Fabric (new).
Rapid-fire one-liners
What is the Virtual DOM and why use it?
An in-memory JS copy of the UI tree. React diffs the new copy against the old and applies only the changed parts to the real DOM, which is expensive to mutate directly.
Difference between props and state?
Props are read-only inputs passed from the parent; state is mutable data the component owns. Both trigger a re-render when they change.
What is reconciliation?
React's diffing algorithm — it compares the new and old Virtual DOM trees and computes the minimal real updates. Same type updates in place; different type replaces the subtree.
Why do lists need a key?
Keys let React match items across renders. With a stable unique id it knows what moved vs what's new. Using the array index breaks on reorder/insert/delete.
CSR vs SSR vs SSG?
CSR builds HTML in the browser after JS loads. SSR builds it on the server per request (fast paint + SEO). SSG builds it once at build time (fastest, CDN-served).
What is hydration?
The browser receives server-rendered HTML, then React attaches event listeners and state to make that static markup interactive.
How do the lifecycle phases map to hooks?
Mount = useEffect with []; update = useEffect with [deps]; unmount = the cleanup function returned from useEffect.
What are the rules of hooks?
Call them only at the top level (not in loops/conditions) and only from React functions, so React can track state by call order.
useMemo vs useCallback?
useMemo caches a computed value; useCallback caches a function's identity. Both prevent unnecessary work/re-renders — use them only on proven hot paths.
How is React Native different from React?
Same React core, but it renders to native views instead of the DOM. You use View/Text/Image, StyleSheet, and onPress; JS talks to native via the bridge or the newer JSI/Fabric.
Is React a framework or a library?
A library — it handles the view layer. You add routing, data fetching, and state management yourself (or use a framework like Next.js built on top of it).
Controlled vs uncontrolled component?
Controlled: React state is the single source of truth for an input's value. Uncontrolled: the DOM holds the value and you read it via a ref when needed.