DEV Community

Cover image for React Expert Revision Handbook
Animesh Pandey
Animesh Pandey

Posted on

React Expert Revision Handbook

📑 Table of Contents


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

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 or memo).

Example

{items.map(item => (
  <Item key={item.id} value={item.value} />
))}
Enter fullscreen mode Exit fullscreen mode

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

🎯 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:

  1. Render Phase (reconciliation):
  • Build Fiber tree, diff with old tree.
  • Pure & interruptible.
  1. 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

  1. Only call hooks in React functions.
  2. 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) { ... }
Enter fullscreen mode Exit fullscreen mode

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

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

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

🎯 Interview One-Liner

“Use useState for simple, isolated state. Use useReducer 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])}>
Enter fullscreen mode Exit fullscreen mode
  • 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 })) }));
Enter fullscreen mode Exit fullscreen mode
  • 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: {...}} };
Enter fullscreen mode Exit fullscreen mode

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

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

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

✅ useDeferredValue

  • Defers updating a value until less urgent work is done.
const deferredQuery = useDeferredValue(query);
Enter fullscreen mode Exit fullscreen mode

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

🎯 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 or prop → 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>;
}
Enter fullscreen mode Exit fullscreen mode

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

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

Usage:

const { on, getTogglerProps } = useToggle();
<button {...getTogglerProps({ onClick: () => console.log("clicked") })}>
  {on ? "On" : "Off"}
</button>
Enter fullscreen mode Exit fullscreen mode

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

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

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

✅ useDeferredValue

  • Defers value updates until React is idle.
const deferredQuery = useDeferredValue(query);
Enter fullscreen mode Exit fullscreen mode

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

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

Fix:

e.persist(); // prevents pooling
Enter fullscreen mode Exit fullscreen mode
  • 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"));
Enter fullscreen mode Exit fullscreen mode

🎯 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

  1. CSS Modules → Scoped per file, no runtime cost.
  2. CSS-in-JS (styled-components, Emotion) → Dynamic styling, runtime overhead.
  3. Utility-first (Tailwind) → Atomic classes, fast builds.
  4. 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>
Enter fullscreen mode Exit fullscreen mode

🎯 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; }
Enter fullscreen mode Exit fullscreen mode
<button style={{ color: "var(--primary)" }}>Click</button>
Enter fullscreen mode Exit fullscreen mode
  • 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>
Enter fullscreen mode Exit fullscreen mode

⚠️ 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).
  • CSRF (Cross-Site Request Forgery):

    • Use SameSite cookies or CSRF tokens.
  • Clickjacking:

    • X-Frame-Options headers.
  • Dependency vulnerabilities:

    • Regular audits with npm audit, Snyk.

⚠️ 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

  1. Manual fetch in useEffect
  • Simple, but prone to race conditions & missing caching.

    1. Global fetchers (React Query, SWR, Apollo)
  • Cache + deduplication + retries built-in.

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

🎯 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(),
});
Enter fullscreen mode Exit fullscreen mode

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

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

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

⚠️ Gotchas

  • Avoid testing internal states (wrapper.state()).
  • Prefer userEvent over fireEvent 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" }));
});
Enter fullscreen mode Exit fullscreen mode

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

⚠️ 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)