React Interview Preparation: React 19 & Next.js Guide
From Fiber Internals and Hook Pitfalls to Server Components and the App Router Rendering Pipeline

What You Must Master to Clear This Track
- Understand the Fiber reconciler's two-phase model (interruptible render phase, synchronous commit phase) and how priority lanes let React interrupt low-priority work for urgent updates.
- Master React 19's Actions, useOptimistic, useFormStatus, and the use() hook for reading promises and context conditionally inside render.
- Know exactly when useEffect fires relative to browser paint versus useLayoutEffect, and how to avoid stale closures and dependency array bugs.
- Be able to explain SSR, SSG, ISR, and React Server Components trade-offs, plus what actually causes hydration mismatches in the App Router.
- Choose the right state tool for the job — local state, lifted state, Context, or an external store — instead of defaulting to global state for everything.
Step-by-Step Study Plan
Follow this sequential roadmap designed to take you from core foundations to advanced architecture and mock interviews.
JSX Mental Model, Component Design & Hook Internals
Rebuild your mental model of JSX-to-createElement compilation, the unidirectional data flow, and go deep on useState, useEffect, useRef, and useReducer semantics.
- •Explain why JSX compiles to React.createElement/jsx-runtime calls and how that produces the element tree React diffs.
- •Trace exactly when useEffect callbacks and cleanups fire relative to render and browser paint.
- •Build 3-4 custom hooks (useDebouncedValue, useFetch with cancellation, useLocalStorage) from scratch.
- •Enable and never silence eslint-plugin-react-hooks exhaustive-deps warnings during practice.
- •Rewrite one class-component lifecycle example as hooks to internalize the componentDidMount/DidUpdate/WillUnmount mapping.
Fiber, Concurrent Rendering, React 19 Features & State Strategy
Study the Fiber tree, render vs commit phases, priority lanes, and React 19's Actions/useOptimistic/use() hook, then map out when to reach for Context vs an external store.
- •Diagram the render phase (work loop, diffing) and commit phase (DOM mutation, layout effects) as two distinct passes.
- •Implement a form using a Server Action, useOptimistic, and useFormStatus end to end.
- •Compare re-render behavior of Context, Zustand/Redux, and prop drilling on the same feature.
- •Profile a component tree with React DevTools Profiler to see which components re-render and why.
- •Practice explaining priority lanes (Sync, Input Continuous, Transition) with a concrete UI example like a search-as-you-type input.
Rendering Strategies, Hydration, Caching Layers & Live Practice
Master SSR/SSG/ISR/RSC trade-offs, the App Router's four caching layers, hydration mismatch debugging, and rehearse full-length React system design interviews.
- •Explain the RSC request/render/hydration pipeline end to end, including what streams and what hydrates.
- •Debug at least 2 real hydration mismatch scenarios (Date.now(), window checks, browser extensions injecting DOM).
- •Complete 4-5 mock interviews covering hook debugging, a component design exercise, and a Next.js rendering-strategy scenario.
- •Always state which parts of a feature you would render on the server vs mark 'use client' before writing code.
- •Time-box whiteboard component design answers to 20 minutes, leaving room for follow-up performance questions.
1. React 19: Actions, the use() Hook & Server Components
React 19 formalizes patterns the community had been hand-rolling for years — pending/optimistic UI, form handling, and server/client composition — into first-class primitives. Interviewers now expect you to know not just hooks, but this new mental model.
An Action is any async function passed to a form's action prop, useTransition, or a Server Action. React automatically tracks its pending state, handles errors, and keeps the UI responsive by treating the update as a non-urgent transition.
Unlike other hooks, use() can be called conditionally and inside loops. It unwraps a Promise (suspending the component until it resolves) or reads a Context value, unifying data-fetching and context consumption under one API.
useOptimistic renders a temporary UI state that reverts or reconciles once the underlying async Action settles. useFormStatus lets nested components read a parent form's pending/data state without prop drilling.
Server Components render entirely on the server (or at build time), never ship their JS to the client, and can read databases/secrets directly. They compose with Client Components ('use client') by passing serializable props and children down.
// app/actions.ts
"use server";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
export async function addTodo(formData: FormData) {
const text = formData.get("text") as string;
await db.todo.create({ data: { text, completed: false } });
revalidatePath("/todos");
}
// app/todo-form.tsx
"use client";
import { useOptimistic, useRef } from "react";
import { addTodo } from "./actions";
type Todo = { id: string; text: string; completed: boolean };
export function TodoForm({ todos }: { todos: Todo[] }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newText: string) => [
...state,
{ id: `temp-${Date.now()}`, text: newText, completed: false },
]
);
const formRef = useRef<HTMLFormElement>(null);
return (
<form
ref={formRef}
action={async (formData) => {
const text = formData.get("text") as string;
addOptimisticTodo(text);
formRef.current?.reset();
await addTodo(formData);
}}
>
<input name="text" placeholder="Add a task" />
<button type="submit">Add</button>
<ul>
{optimisticTodos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</form>
);
}- In interviews, explicitly contrast useOptimistic with manually managing a 'pending' boolean in useState — the interviewer is testing whether you know React now owns that lifecycle.
- Be ready to explain that use() is not a replacement for useEffect-based data fetching in Client Components; it is primarily meant to consume promises created by Server Components or a cache-aware fetcher.
- Calling use() with a promise created fresh on every render (instead of one from a stable cache/Server Component boundary) causes an infinite re-suspend loop.
- Marking an entire page 'use client' just because one small widget needs interactivity, which forfeits the zero-JS benefit of Server Components for the rest of the tree.
2. The Fiber Reconciler & Render-Commit Lifecycle
Since React 16, the Fiber architecture underlies every render. Interviewers use this topic to separate candidates who memorized hook syntax from those who understand what React is actually doing on every update.
A Fiber is a plain JS object representing one unit of work for a component instance — it tracks type, props, state, and pointers (child/sibling/return) forming a linked-list tree, which lets React pause, resume, or abort work instead of relying on the call stack.
React keeps two Fiber trees: 'current' (what's on screen) and 'work-in-progress' (being built). At the end of a successful commit, React simply swaps which tree is current — an O(1) pointer flip rather than rebuilding the UI.
Updates are assigned to lanes (Sync, Input Continuous, Default, Transition, Idle). A urgent lane (e.g. a keystroke) can interrupt in-progress low-priority render work (e.g. a useTransition-wrapped search-results render), keeping input responsive.
During diffing, React compares Fibers of the same type at the same position by key. Matching keys let React reuse the DOM node and its state; mismatched or missing keys (like array indexes on reordered lists) cause unnecessary unmounts/remounts.
How a single setState call travels from scheduling through DOM mutation to the browser paint.
- When asked 'why is useLayoutEffect sometimes necessary,' answer with the pipeline above: it runs synchronously in the commit phase before paint, so it can measure/mutate the DOM without a visible flicker — useEffect cannot make that guarantee.
- Assuming setState is always synchronous — inside React event handlers, React 18+ automatically batches multiple updates into a single render pass, even across Promise/setTimeout boundaries.
- Treating the render phase as side-effect-safe for mutations; because it can be paused, aborted, or re-run, function components must stay pure during render.
3. Hooks Deep-Dive: useEffect Timing, Custom Hooks & Pitfalls
Hook questions are the most common part of any React interview because they expose whether a candidate understands closures, cleanup semantics, and dependency correctness — not just hook names.
useEffect callbacks run asynchronously after the browser has painted, avoiding blocking visual updates. useLayoutEffect runs synchronously immediately after DOM mutations but before paint, used for measuring layout or preventing a flash of incorrect content.
A hook callback captures the props/state values from the render it was created in. If a dependency array omits a reactive value, the callback keeps referencing that render's stale value on every subsequent invocation.
A custom hook is just a function starting with 'use' that calls other hooks; it lets you extract and reuse stateful logic (data fetching, subscriptions, debouncing) across components without changing the component tree, unlike HOCs or render props.
When multiple pieces of state update together in response to the same events (a multi-step form, an undo/redo stack), useReducer centralizes transition logic and makes state changes easier to test and trace than scattered useState calls.
import { useEffect, useState } from "react";
interface FetchState<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
function useFetch<T>(url: string): FetchState<T> {
const [state, setState] = useState<FetchState<T>>({
data: null,
loading: true,
error: null,
});
useEffect(() => {
const controller = new AbortController();
setState((prev) => ({ ...prev, loading: true, error: null }));
fetch(url, { signal: controller.signal })
.then((res) => {
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
return res.json() as Promise<T>;
})
.then((data) => setState({ data, loading: false, error: null }))
.catch((error: Error) => {
if (error.name !== "AbortError") {
setState({ data: null, loading: false, error });
}
});
// Cleanup: aborts the in-flight request if url changes or component unmounts
return () => controller.abort();
}, [url]);
return state;
}- When explaining a dependency array bug, name the mechanism precisely: 'the effect closed over the render-N value of count because count was omitted from the deps array,' not just 'it was stale.'
- Prefer the functional updater form, setCount(c => c + 1), when a new state value depends on the previous one — it removes the need to list the state variable itself as a dependency.
- Returning a cleanup function that references the wrong closure, unsubscribing from a newer subscription instead of the one the effect actually created.
- Putting an object or array literal directly in a dependency array — it is a new reference every render, causing the effect to re-run on every single render.
4. State Management & Next.js App Router Rendering Strategies
Modern React interviews increasingly test system-design-style judgment: choosing the right state tool for a feature, and reasoning about where in the SSR/SSG/ISR/RSC spectrum a page should live in the Next.js App Router.
Local component state (useState/useReducer) for ephemeral UI, lifted state or composition for a few nearby components, Context for low-frequency cross-cutting values (theme, auth session), and an external store (Zustand, Redux Toolkit, Jotai) with selectors for complex or high-frequency global state.
SSR renders per request for freshness; SSG pre-renders at build time for maximum speed on content that rarely changes; ISR statically serves pages but revalidates them on an interval or on-demand; RSC is a rendering model (not tied to timing) where Server Components stream serialized UI and ship zero JS to the client by default.
Hydration attaches event listeners and reconciles React's virtual tree against the server-rendered HTML without re-creating DOM nodes. A mismatch (different output on server vs first client render, e.g. from Date.now() or window checks) forces React to discard and re-render, or throw a hydration error.
Four distinct caches operate together: Request Memoization (dedupes identical fetch calls within one render), the Data Cache (persists fetch results across requests/deploys), the Full Route Cache (caches rendered HTML/RSC payload at build time), and the Router Cache (client-side, caches visited route segments for instant back/forward navigation).
How a request becomes interactive UI in an app mixing Server and Client Components.
- When asked to pick a rendering strategy, always tie the answer to data freshness requirements and traffic pattern, e.g. 'a product page with 10k SKUs updated hourly is a strong ISR candidate with a 3600s revalidate.'
- If asked how to fix a hydration mismatch caused by browser-only APIs, mention moving the value into useEffect/state (so it renders only after mount) rather than reaching for suppressHydrationWarning as a first resort.
- Reaching for Redux/Context to store data that is really server-owned (a fetched list, a user record) instead of using a cache-aware fetcher or Server Components, duplicating a source of truth.
- Assuming 'use client' opts an entire subtree out of streaming/SSR — it only means that component (and its children) hydrate and run in the browser; it is still server-rendered for the initial HTML.
Migrating a Legacy CRA Fintech Dashboard to the Next.js App Router
A fintech analytics team maintained a Create React App dashboard that shipped roughly 1.4MB of JavaScript before a single chart rendered, causing slow, sluggish load times for account managers checking overnight metrics from constrained office networks.
- 1Audited the component tree to separate data-fetching and presentational logic from genuinely interactive widgets (date pickers, drill-down charts).
- 2Migrated top-level dashboard routes to the Next.js App Router, converting static shells and KPI tiles into Server Components that fetch metrics directly from internal APIs.
- 3Isolated interactive pieces into small 'use client' leaf components instead of marking entire pages client-side, keeping most of the tree server-rendered with zero shipped JS.
- 4Replaced a monolithic Redux store with React Query for server-owned cache state, keeping Zustand only for local UI state like open panels and selected filters.
- 5Added per-widget Suspense boundaries with loading.tsx skeletons so above-the-fold KPIs streamed in immediately while slower chart queries resolved separately.
Top Must-Know Interview Questions & Model Answers
Q1: What are the Rules of Hooks, and why must hooks be called unconditionally at the top level of a component?
- •React associates hook state with a Fiber-level array/linked-list, matching the Nth useState call in render 1 to the Nth useState call in render 2.
- •Calling a hook inside a conditional, loop, or after an early return can shift that index between renders, silently attaching the wrong stored state to the wrong hook call.
- •eslint-plugin-react-hooks statically enforces this rule and also validates exhaustive dependency arrays.
Q2: Explain why useEffect runs after paint but useLayoutEffect runs before paint, and when that distinction actually matters.
- •Use useLayoutEffect when you must measure or mutate the DOM (e.g. reading an element's bounding box to position a tooltip) and need that mutation visible in the very first paint, avoiding a flicker.
- •Defaulting to useLayoutEffect everywhere can block paint on slow computations, hurting perceived performance; it should be the exception, not the default.
Q3: What is a Fiber, and how does the Fiber architecture differ from React's old stack-based reconciler?
- •The pre-Fiber (React 15) reconciler recursively walked the tree synchronously via the JS call stack, so a large update could block the main thread until fully complete.
- •Fiber represents the tree as a linked list traversable iteratively, so React's scheduler can yield back to the browser mid-render and resume later — the foundation for concurrent features.
Q4: What problem does the new use() hook solve, and how is it different from calling a normal hook conditionally?
- •Passing a promise to use() suspends the component (triggering the nearest Suspense boundary) until it resolves, then returns the resolved value directly in render.
- •Because use() doesn't rely on call-order-based state like useState, React explicitly permits it inside if-statements and loops, unlike every other built-in hook.
Q5: What is a Server Action, and how does progressive enhancement work for forms built with React 19?
- •Without JS, the browser performs a normal HTML form POST that the framework routes to the Server Action.
- •Once hydrated, React intercepts the submission, calls the action via a fetch-like RPC, and can combine it with useOptimistic/useFormStatus for instant feedback.
Q6: Explain React's concurrent rendering and the priority lanes model in your own words.
- •Lanes include Sync (must flush immediately, e.g. a controlled input keystroke), Input Continuous, Default, and Transition (marked via startTransition/useTransition, allowed to be deferred and even discarded if superseded).
- •This is what makes React 'interruptible': the render phase for a low-priority lane can be paused mid-way and abandoned in favor of finishing a higher-priority lane first.
Q7: What is the difference between SSR, SSG, ISR, and RSC in the Next.js App Router?
- •SSG produces the fastest TTFB by serving pre-built HTML from a CDN but can't reflect data changes without a rebuild.
- •SSR guarantees freshness on every request at the cost of higher server load and TTFB.
- •ISR statically serves a page but revalidates it in the background after a configured interval or on-demand tag/path invalidation, blending SSG's speed with near-fresh data.
- •RSC applies within any of the above: a Server Component fetches and renders on the server, while nested 'use client' components still hydrate and run in the browser.
Q8: What causes a hydration mismatch error, and how do you actually fix one?
- •Common causes: Date.now()/Math.random() in render, checking typeof window/localStorage during render, or browser extensions injecting DOM before hydration runs.
- •The fix is to move the non-deterministic or browser-only logic into useEffect/state so it only affects the DOM after mount, rendering a stable placeholder on both server and first client pass.
- •suppressHydrationWarning should be used sparingly, only for known-safe, intentionally-different values (like a rendered timestamp), never as a blanket fix.
Q9: Compare re-render behavior of the Context API versus an external store like Zustand or Redux.
- •Context has no built-in selector mechanism; a single provider value change re-renders all consumers, which is why co-locating unrelated pieces of state in one Context provider hurts performance at scale.
- •Stores like Zustand/Redux use external subscription (often via useSyncExternalStore) with selector functions, so a component reading store.user won't re-render when store.cart changes.
Q10: Why does a stale closure bug happen inside useEffect or useCallback, and how do you fix it?
- •Every render creates new closures over that render's props/state; omitting a value from useEffect/useCallback's dependency array pins the closure to whatever that value was on the render it was defined.
- •Fixes include adding the missing dependency, using the functional state updater form to avoid needing the value at all, or storing the latest value in a ref for effects that intentionally shouldn't re-run.
Q11: When should you use useMemo or useCallback, and when do they actually hurt more than help?
- •useMemo/useCallback have their own cost: storing the previous value/deps and doing a comparison every render, which can exceed the cost of just recomputing a cheap value.
- •They are most valuable directly upstream of a React.memo child or inside a dependency array of another hook, where referential stability actually changes behavior.
Q12: How would you design a custom hook that safely handles an async request with cancellation on unmount or re-invocation?
- •This prevents setting state on an unmounted component and avoids race conditions where a stale, slower request resolves after a newer one and overwrites fresh data.
- •The hook should expose { data, loading, error } and re-run the effect whenever its real dependencies (like a query parameter) change.
Q13: Explain the difference between the render phase and commit phase, and why only the render phase is interruptible.
- •Because render can be abandoned and retried, any side effects (DOM writes, subscriptions) placed directly in a component body rather than in an effect would be unsafe to run multiple times or partially.
- •The commit phase is intentionally synchronous and uninterruptible precisely because a torn, partially-applied DOM update would be visibly broken.
Q14: Why are array indexes bad keys for dynamic lists, and what specifically breaks?
- •If item 3 is deleted, every item after it shifts to a 'new' index, so React reuses the DOM/state of the wrong item instead of unmounting the deleted one.
- •This is especially visible with uncontrolled inputs, CSS transitions, or component-local state inside list items, which appear to 'stick' to the wrong row.
Q15: What is useOptimistic and when would you reach for it instead of local state?
- •It takes the current confirmed state and an update function, returning a temporary optimistic value that is shown immediately while the real mutation is pending.
- •Once the associated transition/Action completes, React automatically replaces the optimistic value with the real result (or discards it on error), without a manual try/catch rollback.
Q16: How does streaming SSR with Suspense boundaries work in the Next.js App Router?
- •This relies on HTTP chunked transfer encoding — the connection stays open and the server pushes additional HTML/script chunks that swap fallback content in place as data resolves.
- •It lets a page show its header/navigation/above-the-fold content instantly while a slow, data-heavy widget further down streams in separately, improving perceived performance without blocking the whole page.
Q17: What is React.memo, and why doesn't it always prevent a component from re-rendering?
- •An inline arrow function or object literal passed as a prop creates a new reference every parent render, defeating the shallow-equality check unless the parent also memoizes it with useCallback/useMemo.
- •React.memo only affects props comparison for that one component; it has no effect on children re-rendering due to their own state or Context changes.
Q18: How do you decide between local component state, lifted state, Context, and a global store?
- •Lifting state too early leads to prop drilling; introducing a global store too early adds unnecessary complexity and re-render surface area for state only two components actually need.
- •A good heuristic: if the state is derived from or mirrors server data, prefer a server-cache library (React Query/SWR) or Server Components over duplicating it in client global state.
Q19: What are React Server Components, and what can and can't run inside them?
- •They can be async functions that await data directly in the component body, eliminating a separate data-fetching layer for that part of the tree.
- •To add interactivity (onClick, useState, useEffect), you compose in a Client Component marked 'use client', passing it serializable props from the Server Component parent.
Q20: What's the difference between useState's functional updater form and passing a direct value?
- •Calling setCount(count + 1) twice in the same handler only increments once, because both calls close over the same stale count from that render.
- •Calling setCount(prev => prev + 1) twice correctly increments twice, since each functional update receives the result of the previous one in the queue.
Q21: What is the purpose of the 'use client' and 'use server' directives?
- •'use client' doesn't mean the component only renders on the client — it's still server-rendered for the initial HTML, then hydrates; it only changes where the code is included in the JS bundle.
- •'use server' functions are the mechanism behind Server Actions, generating a secure RPC endpoint the client can invoke, without hand-writing a traditional API route.
Q22: How does React batch state updates in event handlers versus async callbacks like setTimeout or a fetch .then()?
- •Automatic batching means multiple setState calls inside a fetch .then() callback now trigger just one re-render instead of one per call, matching the behavior developers previously only got inside onClick handlers.
- •flushSync() is the escape hatch to force a synchronous, unbatched update when you specifically need the DOM updated before the next line of code runs.
Q23: What is the dependency array footgun in useEffect, and how does eslint-plugin-react-hooks help?
- •Omitting a used value to 'stop an effect from re-running too often' produces stale-closure bugs instead of solving the real problem, which is usually that the effect is doing too much or needs restructuring.
- •The lint rule statically analyzes the effect body and flags any referenced reactive value missing from the array, catching bugs before runtime.
Q24: How does React's diffing algorithm decide whether to update a component in place versus unmount and remount it?
- •Changing a <div> to a <span> at the same tree position, or swapping which component renders at that position, forces a full unmount/remount even if the new element looks similar.
- •This is why conditionally rendering entirely different component types for the 'same' UI slot resets local state, while conditionally changing props on the same component type does not.
Q25: Explain the caching layers in the Next.js App Router: Request Memoization, Data Cache, Full Route Cache, and Router Cache.
- •Request Memoization only lives for the duration of one server render, preventing the same data being fetched twice if two components in the tree request the same URL.
- •The Data Cache is what ISR's revalidate option actually controls, and can be invalidated on-demand via revalidateTag/revalidatePath.
- •The Router Cache is purely client-side and can serve stale data briefly on back navigation, which is a common source of 'why didn't my update show up' confusion.
Q26: What is prop drilling, and how does component composition (passing children as props) avoid it without introducing Context?
- •Instead of <Layout data={data}><Sidebar data={data} /></Layout> threading data through Layout, you can render <Layout><Sidebar data={data} /></Layout> directly where data is available, bypassing Layout entirely.
- •This 'slots' pattern (children or named render props) is often a simpler fix than Context for one-off drilling, reserving Context for truly global, many-consumer values.
Q27: What does the React Compiler (automatic memoization) change about how developers write components?
- •It works by understanding React's rules (components/hooks are pure, props/state changes drive re-renders) to safely determine when a value or subtree can be skipped, rather than requiring the developer to manually track dependencies.
- •Manual useMemo/useCallback are still valid and sometimes still necessary (e.g. for referential stability contracts the compiler can't infer), but they become the exception rather than the default habit.
Q28: How would you implement a custom hook using useSyncExternalStore to safely subscribe to an external data source?
- •Without it, a component reading directly from a mutable external source during render risks 'tearing' — different parts of the same tree seeing different snapshots when a concurrent render is interrupted mid-way by a store update.
- •It also requires a getServerSnapshot argument to provide a consistent value during SSR, since the external store may not exist on the server (e.g. window.matchMedia).
Mistakes That Sink Otherwise Strong Candidates
Why it happens: The effect re-runs too often, so removing the offending dependency looks like a quick fix and silences the linter warning.
The fix: Include every reactive value the effect reads; if that causes excessive re-runs, restructure the effect (split it, move logic to an event handler, or store the value in a ref) instead of hiding the dependency.
Why it happens: It's the most convenient value available inside a .map(item, index) call and works fine until the list is reordered, filtered, or has items inserted/removed.
The fix: Key list items by a stable, unique identifier from the underlying data, never by position.
Why it happens: It mirrors familiar imperative JavaScript, and the mutation can even appear to work because React sometimes still re-renders from an unrelated update.
The fix: Always create a new reference (spread syntax, array methods that return new arrays, or a library like Immer) so React's shallow-equality checks correctly detect the change.
Why it happens: The naive fetch-in-effect pattern is what most tutorials teach first, and cancellation is easy to forget.
The fix: Use an AbortController in the cleanup function, or move data fetching to a library (React Query/SWR) or Server Components that already handle cancellation and caching.
Why it happens: Context feels like a lightweight built-in global store, so it's a natural first reach for shared state.
The fix: Split Context by concern and memoize its value, or move high-frequency state into a selector-based external store so unrelated consumers don't re-render on every change.
Why it happens: It's the path of least resistance when a build error demands a client boundary somewhere in the tree.
The fix: Push 'use client' down to the smallest interactive leaf component and keep the surrounding layout and data-fetching as Server Components.
Why it happens: Blog posts and cargo-culted 'best practices' present memoization as always-safe performance hygiene.
The fix: Profile with React DevTools first; memoize only expensive computations or references that must stay stable for a memoized child or a dependency array.
Why it happens: It's easy to forget the server has no window/localStorage and that the same render function runs on both server and first client pass.
The fix: Move browser-only or non-deterministic logic into useEffect so it only affects the DOM after mount, keeping the initial server and client output identical.
Quick-Reference Cheat Sheet
Recommended Practice Quizzes on QuizCluster
Test your retention and prepare for timed live coding and MCQ technical screening rounds:
React & Next.js
Drill React 19 hooks, Fiber rendering internals, and App Router SSR/SSG/ISR/RSC strategies.
JavaScript Engine & React Internals
Test event loop mechanics alongside React's Fiber scheduler, reconciliation, and priority lanes.
JavaScript & TypeScript
Reinforce the closures, async patterns, and type system fundamentals every React question assumes.
Frequently Asked Questions
Do I need to memorize React's internal source code for interviews?
No, but you do need the mental model: Fiber trees, the render vs commit phase split, and priority lanes. Interviewers use these topics to test depth beyond hook syntax, not to test whether you've read the React source line by line.
Is Redux still relevant given Context and Server Components?
Yes, but its scope has narrowed. With React Server Components and Server Actions increasingly owning server data, external stores like Redux or Zustand are now best reserved for genuinely client-only, high-frequency UI state rather than mirroring data the server already owns.
Should I still learn class component lifecycle methods for interviews in 2026?
You rarely need to write new class components, but understanding the conceptual mapping (componentDidMount/componentDidUpdate to useEffect, componentWillUnmount to a cleanup function) is still useful since interviewers use it to probe whether you understand hooks or just memorized their syntax, and legacy codebases still exist.
How much Next.js should a 'React' interview candidate actually know?
Quite a lot in practice. Because the App Router is the dominant way companies ship React today, expect SSR/SSG/ISR/RSC and hydration questions even in interviews framed as 'pure React,' since most teams can't separate the two in production.