π Senior Frontend Engineer / React Developer Interview Handbook
Part 4: Sections 16β20 | NPM β Q&A β Mental Models β Checklist β FAANG Deep Dive
SECTION 16: NPM Package Development
16.1 How npm Install Works Internally
npm install <package>
β
βΌ
1. Check package.json for package name + version range
β
βΌ
2. Query npm registry (registry.npmjs.org)
β Returns package metadata (versions, dependencies, dist tarball URL)
β
βΌ
3. Resolve dependency tree
β Check package-lock.json for locked versions
β Resolve peer/dev/production deps
β
βΌ
4. Download tarballs (.tgz) to npm cache (~/.npm)
β
βΌ
5. Extract to node_modules/
β
βΌ
6. Run lifecycle scripts (preinstall, install, postinstall)
β
βΌ
7. Update package-lock.json
package.json vs package-lock.json
| Β | package.json | package-lock.json |
|---|---|---|
| Written by | Developer | npm (auto-generated) |
| Versions | Ranges (^1.2.3, ~1.2.3) |
Exact versions |
| Committed | Yes | Yes |
| Purpose | Declare intent | Lock exact dependency tree |
| npm install with lock | Uses lock versions | β |
| npm update | Updates within ranges, regenerates lock | β |
Dependency Types
{
"dependencies": {
"react": "^18.0.0" // needed at runtime in production
},
"devDependencies": {
"jest": "^29.0.0" // only needed during development/build
},
"peerDependencies": {
"react": ">=16.8.0" // consumer must provide this β not installed by npm
},
"peerDependenciesMeta": {
"react": { "optional": true }
},
"optionalDependencies": {
"fsevents": "^2.3.2" // install if possible, ok if fails
}
}
When to use peerDependencies: For library packages (React components, plugins). You donβt bundle React into your library β the consuming app provides it. This avoids multiple React instances.
16.2 Semantic Versioning
1 . 2 . 3 - beta.1
β β β β
MAJOR MINOR PATCH Pre-release
β β β
Breaking New feat Bug fix
changes (backward (backward
compat) compat)
npm version ranges:
^1.2.3 β >=1.2.3 <2.0.0 (compatible changes: minor + patch)
~1.2.3 β >=1.2.3 <1.3.0 (patch releases only)
1.2.3 β exactly 1.2.3
* β any version (dangerous!)
>=1.2.3 <2.0.0 β explicit range
16.3 Create an NPM Package β Complete Guide
Step 1: Initialize
mkdir my-react-hooks
cd my-react-hooks
npm init -y
git init
Step 2: Package Structure
my-react-hooks/
βββ src/
β βββ index.ts # main entry, exports everything
β βββ useDebounce.ts
β βββ useLocalStorage.ts
β βββ useIntersection.ts
βββ dist/ # built output (gitignored)
β βββ index.js # CommonJS
β βββ index.mjs # ES Module
β βββ index.d.ts # TypeScript declarations
βββ tests/
β βββ useDebounce.test.ts
βββ package.json
βββ tsconfig.json
βββ vite.config.ts # or rollup.config.js
βββ .npmignore
βββ README.md
Step 3: package.json
{
"name": "@myorg/react-hooks",
"version": "1.0.0",
"description": "Reusable React hooks",
"main": "./dist/index.js", // CommonJS entry (require)
"module": "./dist/index.mjs", // ESM entry (import)
"types": "./dist/index.d.ts", // TypeScript types
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"], // only these files in npm package
"sideEffects": false, // enables tree shaking
"scripts": {
"build": "vite build",
"test": "vitest",
"prepublishOnly": "npm run build && npm test"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
},
"devDependencies": {
"react": "^18.0.0",
"typescript": "^5.0.0",
"vite": "^5.0.0",
"@vitejs/plugin-react": "^4.0.0",
"vitest": "^1.0.0"
},
"keywords": ["react", "hooks", "typescript"],
"license": "MIT",
"repository": { "type": "git", "url": "https://github.com/myorg/react-hooks" }
}
Step 4: Vite Library Mode
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { resolve } from "path";
import dts from "vite-plugin-dts";
export default defineConfig({
plugins: [
react(),
dts({ insertTypesEntry: true }), // generates .d.ts files
],
build: {
lib: {
entry: resolve(__dirname, "src/index.ts"),
name: "ReactHooks",
formats: ["es", "cjs"],
fileName: (format) => `index.${format === "es" ? "mjs" : "js"}`,
},
rollupOptions: {
// Externalize peer dependencies β don't bundle them!
external: ["react", "react-dom", "react/jsx-runtime"],
output: {
globals: { react: "React", "react-dom": "ReactDOM" },
},
},
},
});
Step 5: Source Code
// src/useDebounce.ts
import { useState, useEffect } from "react";
/**
* Debounces a value by the specified delay.
* @param value - The value to debounce
* @param delay - Delay in milliseconds
* @returns The debounced value
*/
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
// src/index.ts
export { useDebounce } from "./useDebounce";
export { useLocalStorage } from "./useLocalStorage";
export { useIntersection } from "./useIntersection";
Step 6: .npmignore
src/
tests/
*.config.ts
*.config.js
.github/
node_modules/
coverage/
Step 7: Publish
# Login
npm login
# Dry run β see what will be published
npm pack --dry-run
# Publish to npm registry
npm publish --access public
# For scoped packages:
npm publish --access public # public scoped
npm publish # private scoped (paid npm account)
# Update version (automatically commits and tags)
npm version patch # 1.0.0 β 1.0.1
npm version minor # 1.0.0 β 1.1.0
npm version major # 1.0.0 β 2.0.0
npm publish
GitHub Packages (Private Registry)
# .npmrc in project root
@myorg:registry=https://npm.pkg.github.com
# Authenticate
npm login --registry=https://npm.pkg.github.com
# package.json β name must be scoped with org
{
"name": "@myorg/react-hooks",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
}
}
16.4 Package Security
# Audit for known vulnerabilities
npm audit
npm audit fix # auto-fix
npm audit fix --force # β οΈ may include breaking changes
# Check what's in your package before publishing
npm pack
# Verify package integrity
npm install --ignore-scripts # don't run install scripts (safer in CI)
SECTION 17: Frequently Asked React Interview Questions
Top 100 React Interview Questions
Fundamentals (1β25)
- What is React and why was it created?
- What is the Virtual DOM? How is it different from Real DOM?
- What is JSX? What does it compile to?
- What is the difference between a React element and a React component?
- What is reconciliation? Explain the diffing algorithm.
- What is the significance of
keyprop in lists? - Why should you not use array index as
key? - What is
React.Fragmentand when do you use it? - What is the difference between controlled and uncontrolled components?
- What are React lifecycle methods? Map them to hooks.
- What is the difference between
propsandstate? - What is prop drilling? How do you avoid it?
- What is
childrenprop? - What is
defaultProps? How to provide defaults in functional components? - What is
PropTypes? How does TypeScript replace it? - What are synthetic events in React?
- What is event delegation in React?
- What is the difference between
onClick={() => fn()}andonClick={fn}? - What is React.StrictMode? What does it do?
- What is a pure component?
- What is a Higher-Order Component (HOC)?
- What are render props?
- What is the Context API?
- What is
React.memo? When should you use it? - What is the difference between
React.ComponentandReact.PureComponent?
Hooks (26β50)
- What are React Hooks? Why were they introduced?
- What are the Rules of Hooks?
- What is
useState? How does it work internally? - What is the difference between
useStateanduseReducer? - What is
useEffect? How does it replace lifecycle methods? - What is the cleanup function in
useEffect? - What happens if you donβt provide a dependency array to
useEffect? - Can
useEffectbe async? How to handle async inuseEffect? - What is
useRef? Why doesnβt it cause re-renders? - What is the difference between
useRefandcreateRef? - What is
useMemo? When should you use it? - What is
useCallback? When should you use it? - What is the difference between
useMemoanduseCallback? - What is
useContext? What are its performance implications? - What is
useReducer? When to prefer it overuseState? - What is
useLayoutEffect? How is it different fromuseEffect? - What is
useImperativeHandle? What isforwardRef? - What is
useId? (React 18) - What is
useDeferredValue? (React 18) - What is
useTransition? (React 18) - What is
useSyncExternalStore? (React 18) - What is
useInsertionEffect? (React 18) - How do you create a custom hook? What are the rules?
- Can custom hooks share state between components?
- What is
useDebugValue?
Performance (51β65)
- Why does a React component re-render?
- How to prevent unnecessary re-renders?
- What is code splitting? How to implement it in React?
- What is
React.lazy? How does it work withSuspense? - What is lazy loading? How is it different from code splitting?
- What is virtualization / windowing? Name React libraries for it.
- What is tree shaking? How to ensure your code is tree-shakeable?
- How to optimize large lists in React?
- How does
useMemohurt performance? - What is debounce? What is throttle? Difference?
- What is the React DevTools Profiler?
- What are Web Vitals? Name the core ones.
- What is bundle analysis? How do you do it?
- How to prefetch routes / data in React?
- What is stale-while-revalidate?
Advanced/Architecture (66β85)
- What is Fiber Architecture? Why was it introduced?
- What is the Render Phase vs Commit Phase?
- What is Concurrent Mode / Concurrent Rendering?
- What is time slicing in React?
- What are Lanes in React 18?
- What is automatic batching in React 18?
- What is the double buffering in Fiber?
- What is
flushSync? - What is Suspense? How does it work internally?
- What are Server Components? How are they different from SSR?
- What is hydration? What is partial hydration?
- What is SSR? SSG? ISR? CSR? Differences?
- What is the React Compiler (React Forget)?
- What are new features in React 19?
- What is
startTransition? - What is the Scheduler package in React?
- What is
$$typeofon a React element? - What is the StrictMode double-invoke behavior?
- What happens when you call
setStatein the render phase? - What is
getDerivedStateFromProps? When to use it?
State Management (86β95)
- When should you use external state management?
- What is Redux? How does it work?
- What is Redux Toolkit? How does it improve Redux?
- What is Immer? How does RTK use it?
- What is Zustand? How is it different from Redux?
- Context API vs Redux β when to use which?
- What is client state vs server state?
- What is React Query? What problems does it solve?
- What is optimistic update? How to implement it in React Query?
- What is Jotai/Recoil atomic state management?
Ecosystem (96β100)
- What is React Router? Whatβs new in v6?
- What is the difference between
BrowserRouterandHashRouter? - What is Next.js? How does it extend React?
- What is Vite? How is it different from webpack?
- What is TypeScript? How does it benefit React development?
Top 30 React Performance Questions
- What causes unnecessary re-renders? How to diagnose?
- How does React.memo work? When is it not useful?
- When does
useCallbackNOT improve performance? - What is the wrong way to use
useMemo? - How to optimize Context to prevent wide re-renders?
- What is virtualization? When must you use it?
- How does
React.lazy+Suspenseimprove performance? - What is the performance impact of inline functions in JSX?
- How to reduce time-to-interactive?
- What is First Contentful Paint (FCP)?
- What is Largest Contentful Paint (LCP)? How to improve it?
- What is Cumulative Layout Shift (CLS)?
- What is Interaction to Next Paint (INP)?
- How does code splitting affect performance metrics?
- What is prefetching vs lazy loading?
- How to profile React apps for performance bottlenecks?
- What is the impact of Context on performance?
- How does automatic batching in React 18 improve performance?
- What is
useDeferredValue? When to use overuseTransition? - What is the waterfall problem in data fetching?
- How does
Suspensehelp with data fetching waterfalls? - What are Web Workers? How to use with React?
- What is service worker caching for React apps?
- How to handle high-frequency events (scroll, resize) in React?
- What is
requestAnimationFrameand when to use in React? - How to reduce bundle size?
- What is tree shaking? How to verify itβs working?
- What is dynamic import()? How is it different from React.lazy?
- How does image optimization affect performance?
- How to implement infinite scroll without performance degradation?
Top 30 React System Design Questions
- Design a real-time collaborative document editor (Google Docs).
- Design Instagramβs news feed.
- Design a real-time chat application.
- Design an e-commerce product listing page.
- Design a dashboard with real-time analytics.
- Design a file upload component with progress.
- Design an infinite scroll news feed.
- Design a multi-step checkout flow.
- Design a type-ahead search component.
- Design a video streaming player component.
- How to design a component library?
- How to structure a large React application?
- How to implement multi-tenancy in a React app?
- How to design an offline-first React app?
- Design a notification system.
- How to implement dark/light theme switching?
- Design a drag-and-drop interface.
- How to handle global error handling in React?
- Design a permission/role-based access control system.
- How would you scale a React app to support 10 teams?
- What is micro frontend architecture? When to use it?
- How to implement feature flags in React?
- Design a rich text editor component.
- How to design a table component that handles 1M rows?
- Design a calendar/scheduling component.
- How to implement optimistic updates?
- Design a form builder with dynamic fields.
- How to design a React app for SEO?
- Design the frontend architecture for a SaaS dashboard.
- How to handle authentication state across multiple tabs?
Top 30 React Hooks Questions
- Why were hooks introduced?
- What are the rules of hooks and why?
- What is the internal data structure behind hooks?
- Why does useState use a linked list?
- What is closure stale state? How
useCallbackcan cause it? - When does
useEffectcleanup run? - Why does
useEffectrun twice in development (Strict Mode)? - When to use
useLayoutEffectoveruseEffect? - What is the difference between
useRefand a closure variable? - How does
useMemocache comparison work? - What is
useReducerdispatch function stability? - How does
useContextsubscription work? - What is
useImperativeHandle? Real-world use case? - What are the limitations of
useCallback? - How to implement
useWhyDidYouUpdatefor debugging? - How to handle race conditions in
useEffect? - How to implement
usePrevious? - How to implement
useAsync/useFetch? - What is
useIdused for? (React 18) - What is the difference between
useTransitionanduseDeferredValue? - How to test custom hooks with
renderHook? - Can you call hooks conditionally? How to work around it?
- What is
useSyncExternalStore? Why was it created? - How to share logic between hooks without sharing state?
- What is a hook factory pattern?
- How to implement infinite scroll with a hook?
- How to implement form state with hooks?
- What is
useOptimistic? (React 19) - What is
useFormStatus? (React 19) - How to implement
useMachineState(XState + hooks)?
Top 30 Production Debugging Questions
- How to diagnose why a component re-renders too often?
- How to find memory leaks in a React app?
- How to debug a white screen of death in production?
- How to debug a broken infinite scroll?
- Component renders correctly in dev but not production β why?
- How to debug stale closure issues?
- How to debug WebSocket disconnections in React?
- How to reproduce and fix a race condition in useEffect?
- How to debug performance regressions?
- How to use React DevTools to find the slowest components?
- What is source mapping? How to use in production debugging?
- How to implement error boundaries effectively?
- How to set up error tracking (Sentry) in React?
- How to debug CORS errors in a React app?
useEffectruns more than expected β how to debug?- How to debug when state is reset unexpectedly?
keyprop causing unexpected unmount β how to diagnose?- How to debug layout shift (CLS) in React?
- How to debug slow initial load?
- How to identify which npm package increased bundle size?
- How to debug hydration mismatch errors in SSR?
- How to debug context value not updating?
- How to trace a React query cache miss?
- How to debug flaky E2E tests?
- How to reproduce a production bug locally?
- How to debug API request waterfalls?
- How to monitor frontend performance in production?
- How to debug React Router navigation issues?
- Event handler called multiple times β how to debug?
- How to debug a micro frontend communication failure?
SECTION 18: React Mental Models
18.1 React as a Pure Function: UI = f(state)
UI = f(state)
Your component is a pure function.
Given the same state, it always produces the same UI.
function UserCard(state) {
return <div>{state.name}</div>;
}
// React's job: call f(state) when state changes, update DOM to match.
Implication: You never imperatively update the DOM. You update state, React figures out the DOM. This is the fundamental mental shift from jQuery.
18.2 React as a Spreadsheet
Think of React state like a spreadsheet:
A1 (firstName) = "Alice"
A2 (lastName) = "Smith"
A3 (fullName) = A1 + " " + A2 β computed, updates automatically
In React:
const [firstName] = useState('Alice');
const [lastName] = useState('Smith');
const fullName = `${firstName} ${lastName}`; // "derived" - no state needed
Mental model: Donβt duplicate derived state. Just like you donβt store fullName in a spreadsheet cell if itβs computed from other cells.
18.3 React Rendering Mental Model (Snapshots)
Each render is a snapshot in time:
function Counter() {
const [count, setCount] = useState(0);
// This click handler "closes over" the count from THIS render
function handleClick() {
setTimeout(() => {
// This 'count' is FROZEN at the value when this render happened
alert(count);
}, 3000);
}
return <button onClick={handleClick}>{count}</button>;
}
If you click, then immediately click again twice, the first alert shows the count from when it was clicked, not the latest count. Each render has its own props, state, and event handlers.
Render 1: count=0, handleClick captures count=0
Render 2: count=1, handleClick captures count=1
Render 3: count=2, handleClick captures count=2
These are 3 separate closures, like 3 separate photos.
18.4 State as a Queue
// Initial state: 0
setCount(count + 1); // Enqueue: replace with 0+1
setCount(count + 1); // Enqueue: replace with 0+1 (stale! same count=0)
setCount(count + 1); // Enqueue: replace with 0+1
// Final result: 1 (not 3!)
// With functional updates:
setCount(c => c + 1); // Enqueue: add 1 to whatever it is
setCount(c => c + 1); // Enqueue: add 1 to whatever it is
setCount(c => c + 1); // Enqueue: add 1 to whatever it is
// Final result: 3 β
Mental model: setState(value) says βreplace with this value at the next render.β setState(fn) says βapply this transformation to the queued value.β
18.5 Reconciliation Mental Model (The Tree Diff)
Old Tree: New Tree:
App App
β β
div div
ββ h1 ββ h1 (same type β update props)
ββ List ββ Table (different type β DESTROY List, CREATE Table!)
β ββ Item[0]
β ββ Item[1]
β ββ Item[2]
Rule: Different type = fresh start.
Same type = update existing node.
Keys = stable identity for list items.
Practical implication: Donβt define components inside other componentsβ render:
// β InputField is recreated every render of Form
function Form() {
function InputField({ label }) {
const [value, setValue] = useState("");
return <input value={value} onChange={(e) => setValue(e.target.value)} />;
}
return <InputField label="Name" />;
}
// React sees a NEW component type each render β unmounts + remounts InputField
// State is lost on every Form re-render!
// β
Define outside
function InputField({ label }) {
const [value, setValue] = useState("");
return <input value={value} onChange={(e) => setValue(e.target.value)} />;
}
function Form() {
return <InputField label="Name" />;
}
18.6 Memoization Mental Model
Without memo:
Parent renders β Child ALWAYS renders
Cost: Parent render time + Child render time
With React.memo:
Parent renders β React asks "did Child's props change?"
Yes (by reference) β Child renders
No (same reference) β Child SKIPS render
Cost: Parent render time + shallow prop comparison
With useMemo/useCallback:
Parent renders β "did this value/function's deps change?"
Yes β recompute
No β return cached value
Cost: Parent render time + dep comparison (smaller than recompute)
When memo is worth it:
- Child render is expensive (big component tree, complex computations)
- Parent re-renders frequently
- Props are referentially stable (objects/functions memoized)
18.7 Effects Mental Model (Synchronization)
Wrong mental model: "This runs when X changes."
Correct mental model: "This synchronizes an external system with React's state."
useEffect(() => {
// synchronize: subscribe to external data source
const sub = chatAPI.subscribe(roomId, handler);
// cleanup: undo the synchronization
return () => chatAPI.unsubscribe(sub);
}, [roomId]); // re-synchronize whenever roomId changes
Practical rule: If you canβt write a cleanup function, your effect is probably not a synchronization β it might be an event handler.
// β Wrong use of effect for one-time event response
useEffect(() => {
if (submitted) {
api.submitForm(data); // side effect from user action
}
}, [submitted, data]);
// β
Put in event handler
function handleSubmit() {
api.submitForm(data);
setSubmitted(true);
}
SECTION 19: Production React Checklist
Performance Checklist
## Performance
- [ ] Core Web Vitals measured (LCP < 2.5s, INP < 200ms, CLS < 0.1)
- [ ] Lighthouse score β₯ 90 for Performance
- [ ] Code splitting implemented (route-based at minimum)
- [ ] Images: WebP format, lazy loading, proper sizes attribute, CDN
- [ ] Fonts: preload critical fonts, font-display: swap
- [ ] Bundle analyzed: no duplicate packages, no unexpectedly large deps
- [ ] Lists with >50 items: virtualization implemented
- [ ] Memoization used correctly (React.memo, useMemo, useCallback)
- [ ] No inline function/object creation in JSX for memoized components
- [ ] useTransition used for non-urgent state updates
- [ ] API calls debounced/throttled where appropriate
- [ ] React Query or SWR for server state (caching, dedup, background refresh)
Security Checklist
## Security
- [ ] No dangerouslySetInnerHTML without DOMPurify sanitization
- [ ] All external URLs validated for safe scheme (http/https only)
- [ ] JWT stored in memory (not localStorage)
- [ ] Refresh token in HttpOnly, Secure, SameSite=Strict cookie
- [ ] CSRF token included in all mutating requests
- [ ] CSP headers configured
- [ ] npm audit clean (no high/critical vulnerabilities)
- [ ] No secrets in frontend code or environment variables committed to git
- [ ] rel="noopener noreferrer" on all external links
- [ ] X-Frame-Options: DENY header set
Accessibility Checklist
## Accessibility
- [ ] Lighthouse Accessibility score β₯ 90
- [ ] All form inputs have associated labels
- [ ] Images have meaningful alt text (empty alt for decorative)
- [ ] Color contrast ratio β₯ 4.5:1 for text
- [ ] Focus management: visible focus ring, logical tab order
- [ ] Keyboard navigation works without mouse
- [ ] ARIA roles used correctly (not over-engineered)
- [ ] Screen reader tested (NVDA/VoiceOver)
- [ ] Error messages associated with form fields via aria-describedby
- [ ] Dynamic content announced via aria-live regions
SEO Checklist
## SEO
- [ ] SSR or SSG for public-facing pages (not CSR)
- [ ] Meaningful <title> per page (React Helmet / Next.js Head)
- [ ] Meta description per page
- [ ] Open Graph tags for social sharing
- [ ] Structured data (JSON-LD) for key page types
- [ ] Canonical URLs set
- [ ] sitemap.xml generated and submitted
- [ ] robots.txt configured correctly
- [ ] Core Web Vitals optimized (Google ranking factor)
Testing Checklist
## Testing
- [ ] Unit tests for all utility functions
- [ ] Component tests for all critical UI components
- [ ] Integration tests for key user flows
- [ ] E2E tests for top 5 critical paths
- [ ] Test coverage > 70% on business logic
- [ ] Tests run in CI on every PR
- [ ] No tests disabled with `.skip` or `xit` without reason
- [ ] MSW set up for API mocking in tests
- [ ] Snapshot tests used sparingly (only for stable UI)
Deployment Checklist
## Deployment
- [ ] CI/CD pipeline runs tests before deploy
- [ ] Environment variables managed securely (secrets manager)
- [ ] Build artifacts versioned (content hashes)
- [ ] CDN configured for static assets
- [ ] Cache headers: 1yr for hashed assets, no-cache for index.html
- [ ] HTTPS enforced with valid certificate
- [ ] Rollback strategy defined
- [ ] Blue/green or canary deployment for zero-downtime
- [ ] Smoke tests after deployment
Monitoring Checklist
## Monitoring & Observability
- [ ] Error tracking configured (Sentry / Datadog RUM)
- [ ] Performance monitoring (Datadog / New Relic / web-vitals library)
- [ ] Real User Monitoring (RUM) for production performance
- [ ] Custom events tracked for business metrics
- [ ] Alerts configured for error rate spikes
- [ ] Source maps uploaded to error tracking service
- [ ] Feature flags in place for gradual rollouts
- [ ] Log aggregation for API errors
SECTION 20: FAANG-Level Deep Dive
20.1 React Fiber Internals β Staff Engineer Level
The Work Loop
Reactβs work loop is the core of the Fiber architecture:
// Simplified work loop (packages/react-reconciler/src/ReactFiberWorkLoop.js)
function workLoop(shouldYield) {
while (workInProgress !== null && !shouldYield()) {
workInProgress = performUnitOfWork(workInProgress);
}
}
function performUnitOfWork(fiber) {
// 1. Begin work: process the fiber
const next = beginWork(fiber.alternate, fiber, renderLanes);
fiber.memoizedProps = fiber.pendingProps;
if (next === null) {
// No children: complete this fiber
completeUnitOfWork(fiber);
}
return next; // return child to process next
}
beginWork β What Happens
beginWork(current, workInProgress, renderLanes):
Based on workInProgress.tag:
FunctionComponent β renderWithHooks()
β calls your function component
β processes hooks (useState, useEffect, etc.)
β returns React elements
β reconcileChildren() to build child fibers
ClassComponent β constructClassInstance() β mountClassInstance()
β calls render()
HostComponent β processUpdateQueue()
β creates DOM element (during mount)
β diffs props (during update)
completeWork β Building the DOM
completeWork(fiber):
For HostComponent (div, span, etc.):
Mount: createDOMElement() β appendAllChildren()
Update: updateProperties() (diff and create update payload)
Bubbles up effects to parent fiber's effectList
20.2 Concurrent Features β Internals
How startTransition Works
// Simplified implementation concept
function startTransition(scope) {
const prevTransition = ReactCurrentBatchConfig.transition;
// Mark: we're in a transition
ReactCurrentBatchConfig.transition = {};
try {
scope(); // run your state updates
} finally {
ReactCurrentBatchConfig.transition = prevTransition;
}
}
// During dispatch:
// If transition is set β assign TransitionLane (low priority)
// If not β assign DefaultLane (normal priority)
How Suspense Works Internally
Component throws a Promise during render:
β
βΌ
React catches the throw (try/catch in renderer)
β
βΌ
Looks up the component tree for nearest <Suspense> boundary
β
βΌ
Shows fallback UI
β
βΌ
Attaches .then() to the thrown Promise
β
βΌ
When Promise resolves: re-renders the suspended subtree
// Suspense-compatible data source (simplified)
function createResource(promise) {
let status = "pending";
let result;
const suspender = promise.then(
(data) => {
status = "success";
result = data;
},
(err) => {
status = "error";
result = err;
}
);
return {
read() {
if (status === "pending") throw suspender; // React catches this!
if (status === "error") throw result; // React Error Boundary catches
if (status === "success") return result; // Happy path
},
};
}
20.3 Server Components (React 19 / Next.js App Router)
Architecture
Traditional SSR:
Server renders HTML β Browser downloads HTML + JS β Hydration
(All HTML + All JS bundle needed)
Server Components:
Server renders RSC Payload (special format) β Browser streams it
Client Components hydrate with interactivity
Server Components: no JS in browser bundle!
Mental Model
// Server Component β runs on server only
// Can directly access DB, file system, secrets
async function ProductPage({ id }) {
const product = await db.products.findById(id); // direct DB access!
return (
<article>
<h1>{product.name}</h1>
<p>{product.description}</p>
{/* Server Component passing data to Client Component */}
<AddToCartButton productId={product.id} price={product.price} />
</article>
);
}
// Client Component β runs on both server (initial HTML) and client
("use client");
function AddToCartButton({ productId, price }) {
const [added, setAdded] = useState(false); // hooks β
(client component)
return (
<button
onClick={() => {
addToCart(productId);
setAdded(true);
}}>
{added ? "β Added" : `Add to Cart ($${price})`}
</button>
);
}
What Server Components Cannot Do
- Use hooks (useState, useEffect, etc.)
- Use browser APIs (window, document)
- Use event handlers (onClick, onChange)
- Use Context (as consumer)
Benefits
- Zero bundle impact: Server components donβt ship JS to client.
- Direct backend access: DB, file system, internal APIs β no intermediate API needed.
- Automatic code splitting: Every Client Component becomes an async chunk.
- Streaming: Server can stream HTML as data resolves.
20.4 Rendering Modes: CSR vs SSR vs SSG vs ISR
CSR (Client-Side Rendering):
Server: serves empty HTML shell
Browser: downloads JS β runs React β renders HTML β fetches data
First load: SLOW (blank screen β JS executes β UI appears)
Subsequent: FAST (SPA navigation)
SEO: BAD (crawlers see empty HTML)
Use: Web apps, dashboards, logged-in areas
SSR (Server-Side Rendering):
Server: runs React β generates full HTML per request β sends to browser
Browser: receives full HTML (fast paint) β JS downloads β hydrates
First load: FAST (full HTML immediately)
SEO: GOOD (crawlers see full HTML)
Server cost: HIGH (renders on every request)
Use: E-commerce, news, dynamic personalized pages
SSG (Static Site Generation):
Build time: runs React β generates full HTML β saves as static files
Server: serves pre-built HTML files
First load: FASTEST (static file from CDN)
SEO: EXCELLENT
Server cost: MINIMAL (CDN)
Con: Stale data (need rebuild to update)
Use: Blogs, documentation, marketing sites
ISR (Incremental Static Regeneration) β Next.js:
Combines SSG + on-demand revalidation
First request: serve pre-built HTML
After revalidation time: regenerate in background
Next request: serve new HTML
Use: E-commerce catalogs, news with reasonable staleness
20.5 Hydration
What Is It?
Hydration is the process of attaching Reactβs event handlers and state to server-rendered HTML.
Server: <button class="btn">Count: 0</button> (static HTML)
β
Browser: React reads existing DOM nodes
Attaches onClick handler to button
Sets up React state
Now: button is interactive β
Hydration Mismatch
// β Server renders different HTML than client
function TimeStamp() {
return <span>{new Date().toISOString()}</span>;
// Server renders: 2024-01-01T00:00:00Z
// Client renders: 2024-01-01T00:00:01Z (slightly later)
// React warning: "Hydration failed because server rendered HTML doesn't match"
}
// β
Use useEffect to render client-only dynamic content
function TimeStamp() {
const [time, setTime] = useState(null); // null on both server and client
useEffect(() => {
setTime(new Date().toISOString()); // only runs client-side
}, []);
return <span>{time ?? "Loading..."}</span>;
}
Partial Hydration / Progressive Hydration
React 18 + Server Components support streaming and partial hydration:
- Different parts of the page hydrate independently.
- Above-fold content hydrates first (visible sooner).
- Below-fold content hydrates lazily.
20.6 React Compiler (React Forget)
What Is It?
The React Compiler (formerly βReact Forgetβ) is a build-time compiler that automatically adds memoization to React components β making useMemo, useCallback, and React.memo largely unnecessary to write manually.
// Before compiler (manual memoization)
function Component({ a, b }) {
const value = useMemo(() => expensiveCompute(a), [a]);
const handler = useCallback(() => doSomething(b), [b]);
return <Child value={value} onAction={handler} />;
}
// After compiler (you write this)
function Component({ a, b }) {
const value = expensiveCompute(a); // compiler adds memoization
const handler = () => doSomething(b); // compiler adds memoization
return <Child value={value} onAction={handler} />;
}
// Compiler generates optimal code with fine-grained memoization
Requirements
- Components must follow React rules (pure render functions, hooks rules).
- If violations detected, compiler skips that component (opt-out).
- Part of React 19, usable via Babel/Vite plugin.
20.7 React 19 Features
New Hooks
// useOptimistic: optimistic UI updates
function LikeButton({ postId, initialLikes }) {
const [likes, setOptimisticLikes] = useOptimistic(
initialLikes,
(state, increment) => state + increment
);
async function handleLike() {
setOptimisticLikes(1); // immediately update UI
await likePost(postId); // actual server call
// If server call succeeds: real state matches
// If fails: automatically reverts to initialLikes
}
return <button onClick={handleLike}>β€οΈ {likes}</button>;
}
// useFormStatus: get status of parent form
function SubmitButton() {
const { pending } = useFormStatus(); // reads from parent <form>
return (
<button disabled={pending}>{pending ? "Submitting..." : "Submit"}</button>
);
}
// useActionState: manage state from form actions
function ContactForm() {
const [state, formAction] = useActionState(
async (prevState, formData) => {
const result = await submitContact(formData);
return result;
},
null // initial state
);
return (
<form action={formAction}>
<input name="email" />
{state?.error && <p>{state.error}</p>}
<SubmitButton />
</form>
);
}
ref as a Prop (No more forwardRef)
// React 19: ref is just a prop
function MyInput({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
// No more:
// const MyInput = React.forwardRef((props, ref) => <input ref={ref} {...props} />);
Other React 19 Changes
use()hook: read a Promise or Context during render (works in conditions!)<Context>as provider (no more<Context.Provider>)- Improved error messages
- Document metadata:
<title>,<link>,<meta>supported directly in components - Asset preloading:
preload,preinitAPIs
20.8 Staff Engineer Interview: React Architecture Question
Q: Your company has a monolithic React app with 50 engineers. It takes 20 minutes to build and deploy. How would you architect a solution?
Framework for answering:
-
Diagnose the problem
- Build time slow: large bundle, complex dependency graph, CI bottleneck?
- Deployment risk: all changes in one deploy, hard to isolate issues.
- Team coordination: merge conflicts, shared globals, unclear ownership.
-
Immediate wins (0β3 months)
- Optimize CI: parallel test execution, caching node_modules.
- Vite migration from webpack: dev server from 2min to instant.
- Code splitting: route-based chunks reduce main bundle.
-
Medium term (3β6 months)
- Feature-sliced design: organize by domain not by type.
- NPM packages for shared utilities/design system.
- Separate CI/CD for design system package.
-
Long term (6β12 months)
- Evaluate micro frontends with Module Federation.
- Domain-based decomposition (teams own vertical slices).
- Each MFE: own repo, own CI/CD, own deployment.
- Shell app composes MFEs.
-
Tradeoffs to mention
- Micro frontends increase runtime complexity.
- Require investment in shared infrastructure (design system, auth).
- Not right for all team sizes β overhead has a cost.
20.9 React Scheduler Internals
Message Channel for Task Scheduling
// React uses MessageChannel for near-immediate async scheduling
// Why not setTimeout(fn, 0)? Minimum 4ms delay in browsers.
// MessageChannel fires in the next task (< 1ms).
const channel = new MessageChannel();
const port = channel.port2;
channel.port1.onmessage = performWork;
function scheduleImmediateWork() {
port.postMessage(null); // fires in next microtask queue β macrotask
}
Priority Queue
Reactβs scheduler maintains a min-heap priority queue of tasks sorted by expiration time:
Tasks sorted by: startTime + timeout
(UserBlocking timeout = 250ms)
(Normal timeout = 5000ms)
workLoop:
while (tasks exist):
peek at top task (soonest to expire)
if currentTime >= task.expirationTime:
mark as OVERDUE β execute now (sync, can't skip)
else if current frame has time left:
execute task
else:
yield (postMessage to resume after browser paint)
End of Part 4 β Sections 16β20
Index of All Files
| File | Sections | Topics |
|---|---|---|
| react-handbook-part1.md | 1β5 | Fundamentals, Core, Hooks, Internals, Performance |
| react-handbook-part2.md | 6β10 | State Mgmt, Router, API, Patterns, System Design |
| react-handbook-part3.md | 11β15 | Machine Coding, Testing, Security, Build, Micro FE |
| react-handbook-part4.md | 16β20 | NPM, Q&A, Mental Models, Checklist, FAANG Internals |