📑 Table of Contents
- React Core Fundamentals
- State Management
- Performance & Optimization
- Advanced Hooks & Patterns
- Concurrent Features & Architecture
- React and the Browser
- Large-Scale Application Architecture
- React with Data & Networking
- Testing & Quality
- React Ecosystem & Future
🟦 React Core Fundamentals (Expert Level)
1. 🎭 Virtual DOM (VDOM)
Definition:
The Virtual DOM is a lightweight in-memory tree representation of the actual DOM. React diffs the VDOM against a previous version to compute the minimal set of changes and applies them to the real DOM.
✅ Key Points
- Avoids expensive DOM mutations by batching and diffing.
- Abstracts away browser DOM inconsistencies.
- Works via reconciliation (diffing algorithm).
⚠️ Gotchas
- VDOM is not always faster — for simple static pages, raw DOM is faster.
- Frequent re-renders of large trees → reconciliation overhead.
- DOM mutations inside
useLayoutEffect
or refs can bypass VDOM — can cause sync issues.
Example
// React maintains a virtual representation
<div className="item">Hello</div>
When state updates → React creates a new VDOM tree, diffs it with old, and mutates only changed nodes.
🎯 Interview One-Liner
“The Virtual DOM is React’s in-memory representation. It enables efficient diffs and minimal DOM updates, though reconciliation itself has cost.”
2. 🧮 Reconciliation Algorithm
Definition:
The process of comparing old and new VDOM trees to decide what to update in the real DOM.
✅ Diffing Rules
- Elements of different types → destroy & recreate subtree.
- Elements of same type → update props and recurse.
- Lists → require keys for identity.
⚠️ Gotchas
- Keys must be stable and unique. Index keys cause bugs if list reorders.
- Changing key forces remount (state reset).
- Deep trees may be skipped if React bails out early (e.g.,
shouldComponentUpdate
ormemo
).
Example
{items.map(item => (
<Item key={item.id} value={item.value} />
))}
🎯 Interview One-Liner
“Reconciliation compares old/new trees. Keys are critical — unstable keys break identity and cause unnecessary remounts.”
3. 🧵 React Fiber Architecture
Definition:
Fiber is React’s reimplementation of the reconciliation algorithm as a linked-list tree of work units, enabling incremental rendering and prioritization.
✅ Key Points
- Fiber node = virtual stack frame (represents component & state).
- Enables time slicing: pause/resume rendering.
-
Each update has a priority level (lane):
- High → user input.
- Low → background rendering.
⚠️ Gotchas
- Fiber means React can pause rendering mid-tree and resume later. Side effects must only run in commit phase.
- Updates may be interrupted and restarted — never rely on render being called exactly once per update.
Example (mental model)
Root Fiber → Child Fiber → Sibling Fiber
Each fiber has: type, pendingProps, memoizedState, return, child, sibling
🎯 Interview One-Liner
“Fiber is React’s linked-list architecture that enables pausing, resuming, and prioritizing work. Render is interruptible, commit is not.”
4. ⚙️ React Rendering Phases
Definition:
React rendering happens in two phases:
- Render Phase (reconciliation):
- Build Fiber tree, diff with old tree.
- Pure & interruptible.
- Commit Phase:
- Apply DOM mutations.
- Run layout effects (
useLayoutEffect
). - Trigger lifecycles.
- Synchronous & non-interruptible.
⚠️ Gotchas
- Render can run multiple times per update (especially in StrictMode).
- Side effects must not run in render phase (causes bugs in concurrent mode).
- Layout effects block paint until executed.
🎯 Interview One-Liner
“Render is pure and may be interrupted or restarted. Commit applies changes to the DOM and always runs synchronously.”
5. ⏳ Component Lifecycle (Class vs Hooks)
✅ Class Lifecycle
- Mount: constructor → render → componentDidMount
- Update: render → componentDidUpdate
- Unmount: componentWillUnmount
✅ Hook Equivalents
-
useEffect
→ componentDidMount/Update (async, after paint). -
useLayoutEffect
→ sync after DOM mutation, before paint. -
useEffect
cleanup /useLayoutEffect
cleanup → componentWillUnmount.
⚠️ Gotchas
- StrictMode double-invokes lifecycle methods in dev.
-
useEffect
runs after paint → may cause flicker for measurements. -
useLayoutEffect
blocks paint → don’t overuse.
🎯 Interview One-Liner
“Class lifecycle maps to hooks.
useEffect
runs async after paint,useLayoutEffect
runs sync before paint. Use the latter sparingly for DOM measurements.”
6. 📜 Rules of Hooks
Definition:
Hooks must be called at the top level of a component or custom hook.
✅ Rules
- Only call hooks in React functions.
- Always call hooks in the same order.
Why?
- Hooks rely on array-like ordering in Fiber.
- Violations break hook state tracking.
⚠️ Gotchas
- Conditional hooks → break order.
- Loops with hooks → break order.
Example
// ❌ Wrong
if (cond) useState(1);
// ✅ Right
const [x, setX] = useState(1);
if (cond) { ... }
🎯 Interview One-Liner
“Hooks are tracked by call order, not names. That’s why they must run unconditionally at the top level.”
7. 🎛️ Context API Internals
Definition:
Provides a way to pass values deeply without prop drilling.
✅ Key Points
- Uses a Provider + Consumer (or useContext).
- Each Context has its own Fiber subscription list.
- Any value change triggers re-render for all consumers, unless optimized.
⚠️ Gotchas
- Performance pitfall: Every consumer re-renders even if not using changed parts.
- Fix: split contexts, use memoized values, or libraries like Zustand.
- Don’t store derived values in Context unnecessarily (causes extra re-renders).
Example
const ThemeContext = React.createContext();
function App() {
return <ThemeContext.Provider value="dark"><Child /></ThemeContext.Provider>
}
🎯 Interview One-Liner
“Context avoids prop drilling but re-renders all consumers on change. Optimize with memoized values or split contexts.”
8. 🎹 Controlled vs Uncontrolled Components
Definition:
- Controlled: Form input state lives in React.
- Uncontrolled: Input state lives in DOM, accessed via refs.
✅ Tradeoffs
- Controlled → easier validation, predictable state, re-render cost.
- Uncontrolled → better performance, harder validation.
⚠️ Gotchas
- Mixing controlled/uncontrolled on same input → React warning.
- Controlled components must update value on every change.
Example
// Controlled
<input value={value} onChange={e => setValue(e.target.value)} />
// Uncontrolled
<input defaultValue="hello" ref={ref} />
🎯 Interview One-Liner
“Controlled inputs sync state to React, while uncontrolled rely on the DOM. Controlled are predictable but heavier.”
🟦 State Management (Built-in + External)
1. 🎛️ useState
vs useReducer
✅ useState
- Simple state, single value updates.
- Good for UI-local state (inputs, toggles).
- Updates replace state, not merge.
✅ useReducer
- More structured, centralizes update logic.
- Better for complex transitions or state machines.
- Reducer function makes updates predictable (pure).
⚠️ Gotchas
-
setState
is async but batched in React 18. - Stale closures if accessing state in async callbacks.
-
useReducer
is stable across re-renders → avoids dependency hell.
Example
function counterReducer(state, action) {
switch (action.type) {
case "inc": return { count: state.count + 1 };
case "dec": return { count: state.count - 1 };
default: return state;
}
}
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
🎯 Interview One-Liner
“Use
useState
for simple, isolated state. UseuseReducer
when state transitions are complex or when debugging predictability matters.”
2. 🌐 Local vs Global State
✅ Local State
- Component-specific (UI interactions).
- Keep as local as possible for performance & maintainability.
✅ Global State
- Shared across large parts of the app (auth, theme, user data).
- Can cause over-rendering if managed poorly.
⚠️ Gotchas
- Overusing global state → hard to reason about.
- Storing derived values globally → redundant re-renders.
🎯 Interview One-Liner
“Keep state as local as possible. Promote to global only when multiple areas need it — overusing global state makes debugging harder.”
3. 📦 Context API for State
✅ Key Points
- Good for low-frequency global state (theme, auth, i18n).
- Bad for high-frequency updates (chat messages, real-time counters).
⚠️ Performance Pitfall
- Any value change re-renders all consumers, even if they don’t use the changed fields.
Fixes
- Split contexts by domain (AuthContext, ThemeContext).
- Use memoized values:
<AuthContext.Provider value={useMemo(() => ({user, login}), [user])}>
- Use selector libraries (Zustand, Jotai).
🎯 Interview One-Liner
“Context works for low-frequency global state, but high-frequency updates cause over-renders. Fix with memoization, splitting, or external stores.”
4. 🗃️ Redux
✅ Strengths
- Predictable state container (single source of truth).
- Strict unidirectional data flow.
- Great for debugging (Redux DevTools, time travel).
⚠️ Weaknesses
- Boilerplate-heavy (reducers, actions).
- Overkill for small apps.
- Frequent re-renders unless using selectors.
Modern Redux (RTK)
- Redux Toolkit simplifies boilerplate.
- Immer for immutable updates.
- Built-in async thunks.
🎯 Interview One-Liner
“Redux provides predictable global state with time-travel debugging. Modern RTK removes boilerplate and uses Immer for immutability.”
5. 🧵 Zustand, Recoil, Jotai (Modern State Libraries)
✅ Zustand
- Minimal, no boilerplate.
- Store is just a hook:
const useStore = create(set => ({ count: 0, inc: () => set(s => ({ count: s.count+1 })) }));
- Fine-grained reactivity (components subscribe to slices).
✅ Recoil
- Atom-based (pieces of state are independent).
- Derived values via selectors.
- Plays well with concurrent rendering.
✅ Jotai
- Primitive atoms (similar to Recoil, simpler).
- Directly use hooks for atom state.
🎯 Interview One-Liner
“Modern libraries like Zustand and Recoil fix Context’s perf issues by letting components subscribe to slices of state instead of the whole store.”
6. 🧩 Event-Driven vs Snapshot State
✅ Snapshot (React default)
- You always render the latest snapshot.
- Changes trigger a re-render.
✅ Event-driven (rare but useful)
- Instead of syncing state → broadcast events (pub/sub).
- Useful for real-time apps (chat, notifications).
🎯 Interview One-Liner
“React state is snapshot-based. For real-time event-driven scenarios, combine with pub/sub systems to avoid re-render storms.”
7. 🗄️ Normalized State
Definition:
Represent relational data in flat structures (like a database).
✅ Why
- Avoids deep nested updates.
- Improves memoization (can compare by ID).
Example
// ❌ Nested
state = { users: [{ id: 1, posts: [{id: 5}]}] };
// ✅ Normalized
state = { users: {1: {id:1, posts:[5]}}, posts: {5: {...}} };
Tools
- Redux Toolkit’s
createEntityAdapter
. - Normalizr library.
🎯 Interview One-Liner
“Normalize relational state to flat structures. This avoids deep updates and enables efficient memoization.”
8. 🧊 Immutable Updates
Definition:
React state must not be mutated directly — immutability ensures predictable diffs.
✅ Tools
- Spread operator,
Object.assign
. - Immer (used by Redux Toolkit).
⚠️ Gotchas
// ❌ Mutation
state.user.name = "Alex";
// ✅ Immutable update
state = { ...state, user: { ...state.user, name: "Alex" } };
🎯 Interview One-Liner
“React relies on immutability to detect changes. Mutating state directly breaks reactivity and can cause stale renders.”
🟦 Performance & Optimization
1. 🧭 Understanding Re-Renders
Definition:
A component re-renders when its state or props change, or when its parent re-renders and passes new references.
✅ Key Points
- React compares new vs old VDOM → reconciles differences.
- Even if output is identical, reconciliation still happens.
- Render ≠ always commit (render can be interrupted).
⚠️ Gotchas
- Passing new object/array literals causes re-renders:
<MyComp data={{x:1}} /> // new object each render
- Context updates re-render all consumers.
-
React.memo
prevents re-render only if props shallow-equal.
🎯 Interview One-Liner
“Re-renders happen on state/prop changes or parent updates. Passing new object references or Context changes are common perf killers.”
2. 🪞 React.memo, useMemo, useCallback
✅ React.memo
- Wraps component → shallowly compares props.
- Prevents unnecessary re-renders.
✅ useMemo
- Memoizes values between renders.
- Expensive computations or derived values.
✅ useCallback
- Memoizes functions → prevents creating new fn refs.
- Useful when passing callbacks to memoized children.
⚠️ Gotchas
-
useMemo/useCallback
themselves add cost — only use when necessary. - Shallow comparison means nested objects still cause false negatives.
- Over-memoization can worsen performance.
🎯 Interview One-Liner
“React.memo avoids re-renders by shallow prop compare. useMemo memoizes values, useCallback memoizes functions. Overusing them can hurt, not help.”
3. 🔄 Batching Updates
Definition:
React groups multiple state updates into one render.
✅ Before React 18
- Batching happened only inside event handlers.
✅ React 18+
- Batching happens in all contexts (timers, async callbacks, promises).
Example
setCount(c => c+1);
setValue(v => v+1);
// React 18 → one render
🎯 Interview One-Liner
“React 18 enables automatic batching everywhere, reducing re-renders. Before 18, batching was limited to event handlers.”
4. ⚡ Concurrent Rendering
Definition:
React 18’s Concurrent Mode (enabled by default) allows rendering to be interruptible, paused, or restarted based on priority.
✅ Key Points
- Enables time slicing — responsive UI during rendering.
- New APIs:
useTransition
,useDeferredValue
. - Doesn’t change final UI, just how React schedules updates.
⚠️ Gotchas
- Render can happen multiple times before commit.
- Side effects must be in commit phase (
useEffect
, not render).
🎯 Interview One-Liner
“Concurrent rendering lets React pause and resume work based on priority. It doesn’t change the UI outcome, only the scheduling.”
5. 🕹️ useTransition & useDeferredValue
✅ useTransition
- Splits updates into urgent vs non-urgent.
- Keeps UI responsive during heavy re-renders.
const [isPending, startTransition] = useTransition();
startTransition(() => setSearchResults(expensiveCompute(query)));
✅ useDeferredValue
- Defers updating a value until less urgent work is done.
const deferredQuery = useDeferredValue(query);
🎯 Interview One-Liner
“useTransition marks updates as non-urgent, keeping UI responsive. useDeferredValue delays expensive renders until idle.”
6. 📦 Virtualization (Large Lists)
Definition:
Render only visible items in a list instead of all at once.
✅ Libraries
-
react-window
,react-virtualized
.
✅ Benefits
- Huge perf gains for 10k+ items.
- Reduces DOM nodes drastically.
⚠️ Gotchas
- Needs correct height calculation.
- Accessibility and SEO challenges (hidden elements not available).
🎯 Interview One-Liner
“Virtualization renders only visible list items. Essential for huge datasets, but requires careful handling of heights and accessibility.”
7. 🎭 Suspense for Data Fetching
Definition:
Suspense lets components “wait” for async data before rendering fallback UI.
✅ Key Points
- Suspense boundaries prevent waterfalls.
- Used with React 18 data frameworks (Next.js, Relay).
- Works with streaming SSR.
⚠️ Gotchas
- Suspense only handles promises, not arbitrary async.
- Error handling must use Error Boundaries.
🎯 Interview One-Liner
“Suspense lets React wait for async data with fallbacks. It simplifies async UI but needs Error Boundaries for failure cases.”
8. 🧩 Avoiding Expensive Renders
✅ Techniques
- Windowing/virtualization for long lists.
- Throttling/debouncing user input.
-
Lazy load components (
React.lazy
). - Selective Context (split providers).
- Selector hooks (subscribe to slices of state).
🎯 Interview One-Liner
“Optimize renders by memoizing, windowing lists, debouncing inputs, lazy loading code, and splitting state into smaller contexts.”
9. 📊 Debugging Performance
✅ Tools
- React DevTools Profiler (flame graph of renders).
-
why-did-you-render
library (detects unnecessary renders). - Browser Performance tab.
✅ Common Symptoms
- Re-render storms.
- Input lag.
- Flickering UI.
🎯 Interview One-Liner
“Use React Profiler and why-did-you-render to spot re-render storms. Input lag or flickering often means wasted renders.”
🟦 Advanced Hooks & Patterns
1. 🛠️ Custom Hooks (Encapsulation & Reuse)
Definition:
Custom hooks are user-defined functions that use other hooks to encapsulate reusable logic.
✅ Key Points
- Encapsulate side effects, subscriptions, state machines.
- Return values (state, handlers) just like built-ins.
- Naming convention:
useSomething
ensures linting rules apply.
Example
function useOnlineStatus() {
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;
}
🎯 Interview One-Liner
“Custom hooks let you extract reusable stateful logic. They’re just functions that call hooks and return state/handlers.”
2. 🧮 Hook Composition vs HOCs vs Render Props
✅ Higher-Order Components (HOCs)
- Function that wraps a component → returns new component.
- Used for cross-cutting concerns (auth, logging).
✅ Render Props
- Component accepts a function as
children
orprop
→ renders custom UI.
✅ Hooks
- Modern replacement for both — composable, less nesting.
⚠️ Gotchas
- HOCs increase component tree depth (“wrapper hell”).
- Render props cause “function as child” nesting.
- Hooks keep tree flat but can cause dependency confusion in
useEffect
.
🎯 Interview One-Liner
“Hooks replace HOCs and Render Props for reusing logic. They’re flatter and composable, but you must manage dependencies carefully.”
3. 🧩 Compound Components Pattern
Definition:
Builds components that work together as a set, sharing state via Context or props.
✅ Example
function Tabs({ children }) {
const [active, setActive] = useState(0);
return (
<TabsContext.Provider value={{active, setActive}}>
{children}
</TabsContext.Provider>
);
}
function TabList({ children }) { return <div>{children}</div>; }
function Tab({ index, children }) {
const {active, setActive} = useContext(TabsContext);
return <button onClick={() => setActive(index)}>{children} {active === index && "*"}</button>;
}
✅ Benefits
- Great for design systems.
- Flexible API (consumer composes layout).
🎯 Interview One-Liner
“Compound components let you build flexible APIs where multiple components share context state, like Tabs, Accordions, or Menus.”
4. 🧮 Controlled vs Uncontrolled Components (Revisited)
- Controlled → Parent owns state.
- Uncontrolled → DOM owns state (access via ref).
✅ Pattern
Some advanced components support both via value
+ defaultValue
.
Example
function Input({ value, defaultValue, onChange }) {
const [internal, setInternal] = useState(defaultValue || "");
const isControlled = value !== undefined;
const val = isControlled ? value : internal;
function handleChange(e) {
if (!isControlled) setInternal(e.target.value);
onChange?.(e);
}
return <input value={val} onChange={handleChange} />;
}
🎯 Interview One-Liner
“Controlled components sync state to React, uncontrolled use refs. Advanced components often support both by checking for
value
prop.”
5. 🔗 Prop Getters Pattern
Definition:
A function returns props you spread onto elements, letting consumers extend behavior.
✅ Example
function useToggle() {
const [on, setOn] = useState(false);
const toggle = () => setOn(o => !o);
function getTogglerProps(props = {}) {
return {
"aria-pressed": on,
onClick: (e) => { props.onClick?.(e); toggle(); },
...props
};
}
return { on, getTogglerProps };
}
Usage:
const { on, getTogglerProps } = useToggle();
<button {...getTogglerProps({ onClick: () => console.log("clicked") })}>
{on ? "On" : "Off"}
</button>
🎯 Interview One-Liner
“Prop Getters let custom hooks merge consumer props with internal behavior — ensuring accessibility and extensibility.”
6. 🎛️ Refs & Imperative APIs
✅ useRef
- Holds mutable values across renders without triggering re-renders.
- Common for DOM access.
✅ forwardRef
- Lets parent pass refs down to child components.
✅ useImperativeHandle
- Expose custom methods from a component via ref.
Example
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus()
}));
return <input ref={inputRef} {...props} />;
});
const ref = useRef();
<FancyInput ref={ref} />;
ref.current.focus();
🎯 Interview One-Liner
“Refs provide imperative escapes. forwardRef passes refs down, useImperativeHandle customizes exposed APIs.”
7. ⏱️ useEffect vs useLayoutEffect
✅ useEffect
- Runs after paint → async, non-blocking.
- Good for subscriptions, async calls.
✅ useLayoutEffect
- Runs synchronously after DOM mutations but before paint.
- Good for DOM measurements, sync mutations.
⚠️ Gotchas
- Using useLayoutEffect for heavy work blocks paint → jank.
- Server-side rendering warns if you use useLayoutEffect (no DOM).
🎯 Interview One-Liner
“useEffect runs async after paint; useLayoutEffect runs sync before paint — use the latter only for DOM measurements.”
8. 🛡️ Error Boundaries
Definition:
React components that catch errors in children and render fallback UI.
✅ Key Points
- Class components only (
componentDidCatch
). - Catch render, lifecycle, commit errors.
- Don’t catch async errors (use try/catch in async).
Example
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(error, info) { console.log(error, info); }
render() { return this.state.hasError ? <h1>Oops</h1> : this.props.children; }
}
🎯 Interview One-Liner
“Error Boundaries catch render/lifecycle errors in children and show fallback UI. They don’t catch async errors or event handlers.”
🟦 React Concurrent Features & Architecture
1. 🧵 Fiber Deep Dive
Definition:
Fiber is React’s internal data structure (a linked list of “units of work”) that enables interruptible, prioritized rendering.
✅ Key Points
-
Fiber Node stores:
- type (component/function)
- pendingProps, memoizedState
- child, sibling, return pointers (tree shape)
Enables React to pause rendering mid-tree, yield to higher-priority work, then resume.
Each Fiber node corresponds to one component instance.
⚠️ Gotchas
- Render can be restarted — never rely on render running exactly once.
- Effects must run in commit phase, not render.
- Updates can be reordered for performance (concurrent mode).
🎯 Interview One-Liner
“Fiber is React’s linked-list tree of work units. It makes rendering interruptible, resumable, and prioritizable.”
2. 🛣️ Lanes & Scheduling (React 18)
Definition:
React assigns updates to lanes — priority buckets for scheduling work.
✅ Key Points
- Urgent → user input (click, typing).
- Normal → data updates.
- Idle → background rendering.
- React merges lanes when possible to batch updates.
⚠️ Gotchas
- Updates may not flush immediately — React may wait until a higher-priority update occurs.
- Debugging lag requires understanding scheduling lanes.
🎯 Interview One-Liner
“React uses lanes to schedule updates by priority. User input gets high priority, background renders get low. This keeps apps responsive.”
3. ⏳ Render vs Commit (Revisited)
-
Render phase
- Build Fiber tree, diff with previous.
- Interruptible.
- No DOM mutations.
-
Commit phase
- Apply DOM changes.
- Run layout effects & lifecycles.
- Non-interruptible.
⚠️ Gotchas
- StrictMode can trigger double-invoked renders to expose side effects.
- Commit phase runs synchronously — avoid blocking.
🎯 Interview One-Liner
“Render is interruptible and pure, commit is synchronous and mutates the DOM. All side effects belong in commit.”
4. ⏱️ Concurrent Rendering
Definition:
Introduced in React 18: rendering is no longer “all or nothing”. React can pause, resume, restart renders.
✅ Benefits
- Keeps input responsive during heavy rendering.
- Splits urgent vs non-urgent updates.
- Enables new APIs (
useTransition
,useDeferredValue
).
⚠️ Gotchas
- Component render functions can run multiple times without committing.
- Must avoid side effects in render (or cause bugs).
🎯 Interview One-Liner
“Concurrent rendering lets React pause and resume work. This keeps UIs responsive but means renders can restart anytime.”
5. 🕹️ Transition API
✅ useTransition
- Marks state updates as non-urgent.
- Keeps urgent work (typing, clicks) responsive.
const [isPending, startTransition] = useTransition();
startTransition(() => {
setSearchResults(expensiveQuery(query));
});
✅ useDeferredValue
- Defers value updates until React is idle.
const deferredQuery = useDeferredValue(query);
🎯 Interview One-Liner
“useTransition splits urgent vs non-urgent updates. useDeferredValue delays heavy computations until idle.”
6. 📦 Suspense for Data (React 18+)
Definition:
Suspense boundaries allow components to wait for promises before rendering fallback UI.
✅ Key Points
- Works with streaming SSR.
- Integrates with frameworks like Next.js (app router).
- Prevents waterfalls by suspending at boundaries.
⚠️ Gotchas
- Suspense doesn’t handle errors → must use Error Boundaries.
- Data fetching must throw a promise to suspend (React Query, Relay do this).
Example
<Suspense fallback={<Spinner />}>
<Profile />
</Suspense>
🎯 Interview One-Liner
“Suspense lets React pause rendering for async data, showing fallback UI. It simplifies async orchestration in concurrent rendering.”
7. 🌐 Streaming SSR & Suspense
Definition:
React 18 added streaming server rendering with Suspense support.
✅ Key Points
- Server sends HTML chunks progressively.
- Suspense boundaries can stream in later.
- Improves TTFB (time to first byte).
⚠️ Gotchas
- Requires careful hydration (client must resume correctly).
- Progressive hydration needed to avoid blocking interactivity.
🎯 Interview One-Liner
“Streaming SSR sends HTML in chunks with Suspense boundaries, improving TTFB and avoiding full-page blocking.”
8. 🧑💻 React Server Components (RSC)
Definition:
New model where some components render on the server only.
✅ Key Points
- RSCs don’t ship JS to client → smaller bundles.
- Can fetch data directly (no hooks).
- Can stream into client tree.
⚠️ Gotchas
- Server & client components must be carefully separated.
- Not fully mature outside Next.js App Router yet.
🎯 Interview One-Liner
“React Server Components let some components render only on the server, reducing client JS and enabling data-fetching at the component level.”
9. 🧩 Hydration & Variants
Definition:
Hydration = React attaches event listeners to server-rendered HTML.
✅ Variants
- Partial Hydration → only hydrate interactive parts.
- Islands Architecture → hydrate independent sections separately.
- Selective Hydration (React 18) → React hydrates higher-priority parts first.
⚠️ Gotchas
- Mismatch between server/client markup → hydration errors.
- Must ensure deterministic render output.
🎯 Interview One-Liner
“Hydration attaches React to server HTML. React 18 does selective hydration, hydrating high-priority parts first.”
10. ⚙️ React Compiler (Meta’s new optimization)
Definition:
Upcoming optimization that auto-memoizes components by analyzing dependencies.
✅ Key Points
- Removes manual
useMemo
/useCallback
needs. - Still experimental, but already used internally at Meta.
🎯 Interview One-Liner
“React Compiler automatically memoizes components by analyzing dependencies, reducing the need for manual useMemo/useCallback.”
🟦 React and the Browser
1. 🎯 React’s Synthetic Event System
Definition:
React wraps native browser events in a SyntheticEvent object for consistency across browsers.
✅ Key Points
- React normalizes event names/behavior.
- Events are pooled for performance (object reused).
- Handlers receive the synthetic event, not the native one.
- If you need the native event → use
event.nativeEvent
.
⚠️ Gotchas
- Event pooling can cause bugs:
function handleClick(e) {
setTimeout(() => console.log(e.type)); // ❌ e is null (pooled)
}
Fix:
e.persist(); // prevents pooling
- Since React 17+, event delegation attaches at the root container, not
document
.
🎯 Interview One-Liner
“React wraps events in a SyntheticEvent for cross-browser consistency. They’re pooled by default, so use
e.persist()
if async access is needed.”
2. 🪟 Portals
Definition:
Portals allow rendering children into a DOM node outside the parent hierarchy.
✅ Use Cases
- Modals, tooltips, dropdowns (avoid z-index hell).
- Fixed-position UI that must escape overflow/position contexts.
⚠️ Gotchas
- Events still bubble through React tree, not DOM hierarchy.
- CSS scoping issues: portal content may escape styling context.
Example
ReactDOM.createPortal(<Modal />, document.getElementById("modal-root"));
🎯 Interview One-Liner
“Portals let you render components outside parent DOM hierarchy but keep React’s event bubbling intact. Ideal for modals & tooltips.”
3. ⏱️ Concurrent Input Handling
Definition:
React 18 uses concurrent rendering to keep inputs responsive during heavy updates.
✅ Patterns
-
useTransition
: defer expensive UI while typing remains smooth. - Debouncing or throttling input handlers.
- Offload expensive work to Web Workers if needed.
⚠️ Gotchas
- Without transitions, large lists can lag when filtering.
- Transition fallback (
isPending
) must show loading state gracefully.
🎯 Interview One-Liner
“Concurrent input handling keeps typing responsive during heavy renders using transitions, deferrals, and sometimes workers.”
4. 🎨 CSS-in-React Strategies
✅ Options
- CSS Modules → Scoped per file, no runtime cost.
- CSS-in-JS (styled-components, Emotion) → Dynamic styling, runtime overhead.
- Utility-first (Tailwind) → Atomic classes, fast builds.
- Vanilla Extract, Linaria → Zero-runtime CSS-in-JS.
✅ Performance Considerations
- CSS-in-JS creates runtime overhead (inserts
<style>
at runtime). - Tailwind/atomic CSS minimizes runtime but can bloat HTML.
- CSS Modules = simple & performant default.
🎯 Interview One-Liner
“CSS-in-React strategies vary: CSS Modules are simple & fast, CSS-in-JS offers flexibility with runtime cost, Tailwind optimizes for dev speed.”
5. ♿ Accessibility (a11y)
Definition:
Ensuring UI works for all users, including assistive technologies.
✅ Key Points
- Use semantic HTML (
<button>
instead of<div onClick>
). - ARIA roles and attributes for assistive tools.
- Keyboard navigation (tab order, focus management).
- Color contrast compliance (WCAG AA/AAA).
-
aria-live
regions for async updates.
⚠️ Gotchas
- Custom components (e.g.,
<div role="button">
) require manual keyboard handlers. - Portals can trap focus if modals don’t manage it.
Example
<button aria-pressed={on}>Toggle</button>
🎯 Interview One-Liner
“Accessible React means using semantic HTML, ARIA attributes, and proper focus management. Accessibility isn’t optional at scale.”
6. ⚡ Browser APIs in React
✅ Common Integrations
- IntersectionObserver → lazy load images, infinite scroll.
- ResizeObserver → adapt to element size changes.
- MutationObserver → detect DOM mutations.
- requestIdleCallback → schedule background work.
⚠️ Gotchas
- Must clean up observers in
useEffect
cleanup. - Observers fire frequently → debounce or throttle updates.
🎯 Interview One-Liner
“React integrates with browser observers (Intersection, Resize, Mutation) for performance-sensitive UIs. Always clean up listeners.”
7. 🧩 Browser Rendering vs React Rendering
✅ Browser Rendering
- HTML → DOM → CSSOM → Render Tree → Layout → Paint → Composite.
✅ React Rendering
- VDOM diff → Fiber scheduling → Commit → DOM mutation → Browser rendering pipeline.
⚠️ Gotchas
- React may skip DOM updates if VDOM diff sees no changes.
- But every render still costs JS time → optimize unnecessary renders.
🎯 Interview One-Liner
“Browser rendering = layout/paint. React rendering = VDOM diff → DOM mutation. Both must be optimized separately.”
🟦 Large-Scale React Application Architecture
1. 🧱 Component-Driven Development (CDD)
Definition:
Build applications from small reusable components upward, using a design system.
✅ Key Points
- Atomic Design: Atoms → Molecules → Organisms → Templates → Pages.
- Storybook or Ladle for component isolation.
- Components must be stateless + composable where possible.
⚠️ Gotchas
- Too much abstraction leads to “prop soup.”
- Teams must align on design tokens (spacing, colors, typography).
🎯 Interview One-Liner
“CDD means building from reusable components, often with a design system, to scale consistency across teams.”
2. 🎨 Multi-Tenant Theming
Definition:
Supporting multiple brands or tenants from the same codebase.
✅ Techniques
- CSS Variables: Themeable at runtime:
:root { --primary: blue; }
[data-theme="dark"] { --primary: black; }
<button style={{ color: "var(--primary)" }}>Click</button>
- Context Providers: Provide theme object via React context.
- Design Tokens: Abstract theme into JSON tokens → consumed by CSS-in-JS, CSS vars, or native CSS.
⚠️ Gotchas
- Context re-renders on theme switch.
- Dynamic imports for brand assets.
- Multi-tenant SSR must inject correct theme per request.
🎯 Interview One-Liner
“Multi-tenant theming is solved with design tokens + CSS variables, allowing runtime theme switching without rebuilds.”
3. 🗂️ Monorepos & Code Sharing
✅ Approaches
- Turborepo / Nx: Efficient build & caching.
- Yarn Workspaces / pnpm Workspaces: Share deps.
- Component packages: Internal NPM libraries for design system.
⚠️ Gotchas
- Dependency hoisting issues.
- Cross-package version drift.
- Need CI/CD pipelines that handle partial builds.
🎯 Interview One-Liner
“Monorepos with tools like Nx/Turborepo enable shared design systems and libraries, but need caching and dependency management.”
4. 🌍 Micro-Frontends (Module Federation)
Definition:
Splitting large apps into independently deployable React apps.
✅ Key Points
- Webpack Module Federation: load remote components at runtime.
- Teams deploy independently, reducing coordination.
- Shared dependencies (React, design system) must be singleton.
⚠️ Gotchas
- Cross-microfrontend routing.
- State sharing between MFEs is tricky.
- Performance hit if federation is misconfigured (duplicate Reacts!).
🎯 Interview One-Liner
“Micro-frontends split large React apps into independently deployable modules, often via Module Federation. Great for org scaling, tricky for state & routing.”
5. 🛡️ Error Boundaries at Scale
✅ Patterns
- Wrap critical UI chunks (e.g., dashboard widgets).
- Provide segmented recovery → one widget fails, rest continue.
- Show fallback UI with retry.
Example
<ErrorBoundary fallback={<RetryButton />}>
<Widget />
</ErrorBoundary>
⚠️ Gotchas
- Don’t wrap the whole app with one boundary — loses isolation.
- Errors in async code aren’t caught.
🎯 Interview One-Liner
“At scale, error boundaries must isolate failures per feature, ensuring one broken widget doesn’t take down the entire app.”
6. 📊 Logging, Monitoring, Observability
✅ Key Points
-
Frontend Observability includes:
- Error tracking (Sentry, Datadog, New Relic).
- Performance metrics (LCP, FID/INP, CLS).
- User interactions (heatmaps, logs).
Centralized logging pipeline → correlate frontend errors with backend logs.
⚠️ Gotchas
- GDPR/PII compliance: don’t log sensitive data.
- Sampling needed at scale (don’t log every keystroke).
🎯 Interview One-Liner
“Frontend observability at scale means error tracking + performance metrics + logs, tied to backend systems. Logging must respect privacy laws.”
7. 🔒 Security in React Apps
✅ Common Threats
-
XSS (Cross-Site Scripting):
- Avoid
dangerouslySetInnerHTML
. - Sanitize user input (DOMPurify).
- Avoid
-
CSRF (Cross-Site Request Forgery):
- Use SameSite cookies or CSRF tokens.
-
Clickjacking:
- X-Frame-Options headers.
-
Dependency vulnerabilities:
- Regular audits with
npm audit
, Snyk.
- Regular audits with
⚠️ Gotchas
- Don’t trust client-side validation → always validate server-side.
- Don’t roll your own sanitizer.
🎯 Interview One-Liner
“React itself mitigates XSS by escaping content, but security requires sanitizing inputs, protecting cookies, and hardening dependencies.”
8. 🏗️ Scalability Best Practices
- Code splitting → lazy load per route.
- Component boundaries → minimize prop drilling, use context sparingly.
- Selective hydration → hydrate only critical UI.
- Consistent architecture → enforce with ESLint + TypeScript.
- Team-level contracts → clear ownership of shared libraries.
🎯 Interview One-Liner
“Scaling React apps requires modular architecture, code splitting, selective hydration, and strong governance over shared libraries.”
🟦 React with Data & Networking
1. 📡 Data Fetching Strategies
✅ Approaches
- Manual fetch in useEffect
-
Simple, but prone to race conditions & missing caching.
- Global fetchers (React Query, SWR, Apollo)
-
Cache + deduplication + retries built-in.
- Server Components (RSC)
Data fetched on the server → no client fetch needed.
⚠️ Gotchas
-
useEffect(fetch)
→ risks double-fetch in StrictMode. - Must abort stale requests (
AbortController
). - Data fetching belongs outside render → don’t fetch inside components without memoization.
🎯 Interview One-Liner
“Manual fetching works for small apps, but React Query/SWR handle caching, retries, deduplication. RSC moves fetching server-side.”
2. 🗃️ Caching Approaches
✅ Snapshot Cache (React Query, SWR)
- Store last response in cache.
- Deduplicate identical queries.
-
Stale-while-revalidate pattern:
- Show cached data immediately.
- Refresh in background.
✅ Normalized Cache (Apollo, Relay)
- Cache data by entity ID (like a client-side DB).
- Avoids duplicate entities in memory.
⚠️ Gotchas
- Normalized caching = more boilerplate.
- Snapshot caching = easier, but duplicates possible.
🎯 Interview One-Liner
“Snapshot caches store responses; normalized caches deduplicate entities by ID. Use normalized caching when relational data needs consistency.”
3. 🕹️ Suspense for Data Fetching
Definition:
React Suspense lets components “pause” until a Promise resolves.
✅ Key Points
- Works with data libraries that throw promises.
- Boundaries prevent waterfall loading.
- Enables streaming SSR.
⚠️ Gotchas
- Must combine with Error Boundaries.
- Not production-ready for all cases yet (needs framework support).
Example
<Suspense fallback={<Spinner />}>
<Profile />
</Suspense>
🎯 Interview One-Liner
“Suspense lets components wait for promises, showing fallbacks instead of loaders everywhere.”
4. 🔄 Optimistic UI & Rollbacks
Definition:
Update the UI immediately on user action, then reconcile with server response.
✅ Key Points
- Increases responsiveness.
- Requires rollback if server rejects update.
Example (React Query)
mutate(newTodo, {
optimisticUpdate: cache => [...cache, newTodo],
onError: (err, _, rollback) => rollback(),
});
⚠️ Gotchas
- Rollbacks must restore consistent state.
- Concurrency issues if multiple mutations overlap.
🎯 Interview One-Liner
“Optimistic UI updates immediately for responsiveness, but requires rollback on failure. Libraries like React Query automate this.”
5. 🌊 Streaming Data (Realtime)
✅ Approaches
- WebSockets: Full-duplex, bidirectional.
- Server-Sent Events (SSE): One-way streaming from server → client.
- GraphQL Subscriptions: Built on WebSockets.
✅ React Integration
- Store messages in state or external store (Zustand).
- Use Suspense for initial load, event-driven updates after.
⚠️ Gotchas
- Must handle reconnects.
- Avoid memory leaks by unsubscribing on unmount.
- Overusing Context for streaming data → re-renders every message.
🎯 Interview One-Liner
“Real-time data uses WebSockets, SSE, or GraphQL subscriptions. Integrate with React using stores or selectors to avoid re-render storms.”
6. ⚠️ Handling Race Conditions
✅ Problem
If a user types quickly, multiple fetches may return out of order.
✅ Solutions
- AbortController: cancel stale requests.
- Latest-only strategy: track request ID.
- Data libraries: React Query handles deduplication.
Example
const controller = new AbortController();
fetch("/api?q=term", { signal: controller.signal });
controller.abort(); // cancel previous request
🎯 Interview One-Liner
“Prevent race conditions by aborting stale requests (AbortController) or using libraries with deduplication.”
7. 🧩 Error Handling in Data
✅ Patterns
- Wrap fetches with Error Boundaries.
- Show segmented error UI (not one giant crash).
- Retry with exponential backoff.
Example (React Query)
useQuery("todos", fetchTodos, { retry: 3, retryDelay: 2000 });
🎯 Interview One-Liner
“Handle data errors gracefully: retries, error boundaries, and segmented fallback UI.”
8. ⚡ Data Prefetching & Dehydration
✅ Prefetching
- Fetch data before navigation → instant page load.
- Frameworks like Next.js, Remix automate this.
✅ Dehydration
- Server fetches data → serializes into HTML → client hydrates cache.
🎯 Interview One-Liner
“Prefetching and dehydration make data instantly available on navigation by preloading or hydrating caches.”
🟦 Testing & Quality in React
1. 🧪 Testing Levels in React
✅ Unit Tests
- Smallest piece (function, hook, component).
- Isolated from external systems.
✅ Integration Tests
- Multiple components working together.
- Focus on behavior (e.g., form validation).
✅ E2E (End-to-End) Tests
- Full app in browser (Cypress, Playwright).
- Test real user flows (login, checkout).
⚠️ Gotchas
- Too many unit tests = brittle, low confidence.
- E2E tests = slow, flakier, but higher confidence.
- Best strategy = Testing Pyramid (more unit, fewer E2E).
🎯 Interview One-Liner
“Use a pyramid: many unit tests, fewer integration tests, and critical E2E flows. Don’t over-invest in one level.”
2. 📚 React Testing Library (RTL)
Definition:
The de-facto standard for testing React components.
✅ Key Points
- Encourages testing behavior, not implementation.
- Query DOM with role, text, label instead of class names.
- Built on top of DOM Testing Library.
Example
render(<button>Click</button>);
fireEvent.click(screen.getByText("Click"));
expect(screen.getByRole("button")).toBeEnabled();
⚠️ Gotchas
- Avoid testing internal states (
wrapper.state()
). - Prefer
userEvent
overfireEvent
for realistic interactions.
🎯 Interview One-Liner
“RTL tests React by user behavior, not internals — query by role/label, simulate real events with userEvent.”
3. 🧑🔬 Snapshot Testing
Definition:
Tests that render component → compare output to saved snapshot.
✅ Key Points
- Fast way to catch unexpected UI changes.
- Great for static, predictable components (icons, design tokens).
⚠️ Gotchas
- Overused snapshots → noisy diffs, brittle tests.
- Not a substitute for behavior tests.
🎯 Interview One-Liner
“Snapshots are useful for static UI checks, but overusing them leads to brittle tests. Prefer behavioral assertions.”
4. 🔌 Mocking APIs
✅ Common Tools
- jest.mock for modules.
-
fetch mocks with
jest-fetch-mock
. - Mock Service Worker (MSW): intercepts fetch/XHR → simulates API at network layer.
✅ MSW Example
rest.get("/user", (req, res, ctx) => {
return res(ctx.json({ name: "Alice" }));
});
⚠️ Gotchas
- Don’t mock too low-level → tests become unrealistic.
- MSW > manual mocks because it simulates the network layer.
🎯 Interview One-Liner
“Mock APIs at the network layer with MSW for realistic tests. Avoid low-level mocks that make tests lie.”
5. 🎭 E2E Testing (Cypress / Playwright)
✅ Key Points
- Simulate full browser environment.
- Test critical flows: login, checkout, dashboard.
- Integrates with CI pipelines.
✅ Differences
- Cypress: simple API, auto-wait, great ecosystem.
- Playwright: faster, better cross-browser & parallel support.
⚠️ Gotchas
- Flaky tests from network delays → fix with retries or MSW.
- Keep E2E tests minimal but critical (happy path + critical edge cases).
🎯 Interview One-Liner
“Use E2E tests for mission-critical flows. Cypress is popular, Playwright is faster and cross-browser. Keep them lean.”
6. 📊 Performance Testing
✅ Tools
- React Profiler API → measure render times.
- Lighthouse → web vitals (LCP, FID/INP, CLS).
- WebPageTest for network analysis.
✅ Strategies
- Write automated perf budgets → fail CI if LCP/CLS regress.
- Use flame graphs in Profiler to find re-render storms.
🎯 Interview One-Liner
“Performance tests track user-centric metrics (LCP, INP, CLS). Use React Profiler + Lighthouse, and enforce budgets in CI.”
7. 🧩 Testing Hooks
✅ Tools
-
@testing-library/react-hooks (deprecated, now in
@testing-library/react
).
Example
function useCounter() {
const [c, setC] = useState(0);
return { c, inc: () => setC(c+1) };
}
const { result } = renderHook(() => useCounter());
act(() => result.current.inc());
expect(result.current.c).toBe(1);
⚠️ Gotchas
- Always wrap state updates in
act()
. - Don’t over-test hooks — test their consumer components instead.
🎯 Interview One-Liner
“Hooks can be tested directly with renderHook, but prefer testing components that consume them for realistic behavior.”
8. 🛡️ Best Practices for React Testing
- Test user behavior, not implementation.
- Minimize mocks → prefer integration-level tests.
- Keep snapshots small and targeted.
- Use MSW for realistic API mocking.
- Focus E2E tests on critical flows only.
- Measure performance with budgets in CI.
- Maintain test pyramids → don’t drown in E2E tests.
🟦 React Ecosystem & Future
1. 🌐 Next.js Internals
Definition:
Next.js is the most popular React meta-framework, adding SSR, routing, and data-fetching.
✅ Rendering Modes
- SSG (Static Site Generation): Pre-render at build time.
- SSR (Server-Side Rendering): Render per request.
- ISR (Incremental Static Regeneration): Re-generate stale pages on demand.
- Streaming SSR (React 18): Progressive HTML streaming.
✅ Routing
- Pages router (legacy).
- App router (React 18 Suspense + Server Components).
⚠️ Gotchas
- Mixing SSG + client hydration can cause mismatch errors.
- ISR requires cache invalidation strategy.
🎯 Interview One-Liner
“Next.js supports SSG, SSR, ISR, and streaming SSR. Its App Router integrates React Server Components for hybrid server+client rendering.”
2. 🎭 Remix
Definition:
A full-stack React framework focused on web fundamentals.
✅ Key Points
- Loaders & Actions: Server APIs for data & mutations.
- Nested Routing: Data & layout are scoped per route.
- Progressive Enhancement: Works even without JS.
⚠️ Gotchas
- Tighter coupling to HTTP (good or bad depending on team).
- Smaller ecosystem compared to Next.js.
🎯 Interview One-Liner
“Remix embraces the web platform: loaders/actions for data, nested routes for composition, and progressive enhancement by default.”
3. 🧩 React Server Components (RSC)
Definition:
React components that render only on the server, never shipping JS to the client.
✅ Benefits
- Smaller client bundles.
- Fetch data directly (no hooks needed).
- Seamless integration with client components.
⚠️ Gotchas
- Not yet widely supported outside Next.js App Router.
- Requires strict separation between server & client components.
🎯 Interview One-Liner
“React Server Components render only on the server, reducing client JS. They fetch data directly and stream into client trees.”
4. ⚡ React Compiler (Future)
Definition:
Meta’s upcoming optimization tool that auto-memoizes components.
✅ Key Points
- Removes manual need for
useMemo
/useCallback
. - Already in production at Meta (as of 2024–25).
- Analyzes dependency usage at build-time.
🎯 Interview One-Liner
“React Compiler auto-memoizes components, eliminating most manual useMemo/useCallback. It’s already in use at Meta.”
5. 📱 React Native
✅ Key Points
- Same React API, renders to native views (iOS/Android).
- Uses a bridge (JS ↔ native).
- New architecture: JSI + Fabric renderer + TurboModules → faster, less overhead.
⚠️ Gotchas
- Not true “write once, run anywhere” → platform-specific tuning still needed.
- Performance depends on new architecture adoption.
🎯 Interview One-Liner
“React Native shares React’s model but renders native components. Its new architecture (Fabric/JSI) reduces bridge overhead.”
6. 🧪 Alternative Frameworks
✅ Preact
- Lightweight React alternative (~3KB).
- Same API, drop-in for React (with aliasing).
- Used in performance-critical apps.
✅ Solid.js
- Fine-grained reactivity (signals instead of VDOM).
- Much faster for many scenarios.
✅ Qwik
- Resumability: ships zero JS initially, resumes state on demand.
- Solves hydration overhead in huge apps.
🎯 Interview One-Liner
“Alternatives like Preact (lightweight React), Solid (fine-grained reactivity), and Qwik (resumable apps) push forward new performance models.”
7. 🔄 Migration Strategies
✅ Class → Hooks
- Incrementally refactor components.
- Wrap legacy lifecycles in custom hooks.
✅ Legacy React → Modern (Concurrent + Suspense)
- Use
StrictMode
to surface unsafe lifecycles. - Refactor
componentWillMount
/componentWillReceiveProps
. - Replace legacy Context API with new API.
✅ Monolith → Micro-Frontends
- Strangle pattern: carve out routes/modules.
- Share design system first.
🎯 Interview One-Liner
“Migrations must be incremental: class → hooks, legacy → concurrent features, monolith → micro-frontends via strangle pattern.”
8. 🔮 Future of React
✅ Trends
- React Server Components → data + rendering shift server-side.
- Streaming SSR → better TTFB.
- React Compiler → auto-memoization.
- Signals (inspired by Solid.js) → may influence React state model.
- Concurrent UI as default → more user-perceived responsiveness.
🎯 Interview One-Liner
“React’s future focuses on server components, streaming SSR, auto-memoization via React Compiler, and adopting ideas from signals-based reactivity.”
✅ Summary (Full Handbook)
This React handbook covers staff/architect-level depth:
- React Core Fundamentals (VDOM, reconciliation, Fiber, phases, lifecycle, hooks rules, context, controlled/uncontrolled inputs)
- State Management (useState vs useReducer, local vs global, Context, Redux/RTK, Zustand/Recoil/Jotai, snapshot vs event-driven, normalization, immutability)
- Performance & Optimization (re-renders, memoization, batching, concurrent rendering, transitions, virtualization, Suspense, profiling)
- Advanced Hooks & Patterns (custom hooks, HOCs vs render props, compound components, controlled/uncontrolled, prop getters, refs & imperative APIs, useEffect vs useLayoutEffect, error boundaries)
- Concurrent Features & Architecture (Fiber, lanes, render vs commit, concurrent rendering, transitions, Suspense, streaming SSR, RSC, hydration, React Compiler)
- React and the Browser (synthetic events, portals, concurrent input handling, CSS strategies, accessibility, browser observers, rendering pipeline)
- Large-Scale Architecture (CDD, theming, monorepos, micro-frontends, error boundaries, observability, security, scalability best practices)
- React with Data (fetching, caching, Suspense, optimistic UI, streaming, race conditions, error handling, prefetching & dehydration)
- Testing & Quality (pyramid, RTL, snapshots, MSW, Cypress/Playwright, performance testing, hooks testing, best practices)
- Ecosystem & Future (Next.js, Remix, RSC, Compiler, React Native, alternatives like Preact/Solid/Qwik, migration strategies, future trends)
Top comments (0)