Skip to main content

Junior React Interview Questions

Curated Junior-level React interview questions for developers targeting junior positions. 35 questions available.

Last updated:

React Interview Questions & Answers

Skip to Questions

Welcome to our comprehensive collection of React interview questions and answers. This page contains expertly curated interview questions covering all aspects of React, from fundamental concepts to advanced topics. Whether you're preparing for an entry-level position or a senior role, you'll find questions tailored to your experience level.

Our React interview questions are designed to help you:

  • Understand core concepts and best practices in React
  • Prepare for technical interviews at all experience levels
  • Master both theoretical knowledge and practical application
  • Build confidence for your next React interview

Each question includes detailed answers and explanations to help you understand not just what the answer is, but why it's correct. We cover topics ranging from basic React concepts to advanced scenarios that you might encounter in senior-level interviews.

Use the filters below to find questions by difficulty level (Entry, Junior, Mid, Senior, Expert) or focus specifically on code challenges. Each question is carefully crafted to reflect real-world interview scenarios you'll encounter at top tech companies, startups, and MNCs.

Questions

35 questions
Q1:

How does React reconcile two virtual DOM trees during re-rendering?

Junior

Answer

React uses its diffing algorithm to compare the previous and next virtual DOM nodes. It reuses elements with the same type and key while replacing mismatches, ensuring minimal DOM operations.
Quick Summary: React's diffing algorithm compares two virtual DOM trees top-down. Elements of different types → full subtree replacement. Same type → compare props and update changed ones. Keys in lists → identify which items moved, were added, or removed. This O(n) heuristic is fast enough for most real-world UIs.
Q2:

Why is the render process pure but the commit phase is not in React?

Junior

Answer

The render phase only calculates changes and contains no side effects, making it pure. The commit phase applies changes to the DOM, causing side effects and making it impure.
Quick Summary: The render phase is pure — React may run it multiple times, discard results, or run it in parallel. No DOM mutations happen here. The commit phase is impure — React applies all DOM changes in one go. This two-phase design lets React interrupt rendering safely while guaranteeing that DOM updates are atomic and consistent.
Q3:

What problem do React Server Components solve?

Junior

Answer

They reduce client bundle size by performing data fetching and heavy computation on the server and sending lightweight serialized output to the client.
Quick Summary: Server Components eliminate the need to fetch data on the client and ship that data-fetching code to the browser. Data is fetched on the server, close to the database, and only the rendered output goes to the client. This reduces bundle size, eliminates client-server waterfalls, and keeps API keys and DB connections server-side.
Q4:

Why is data fetching in useEffect considered an anti-pattern in React 18+?

Junior

Answer

Fetching in useEffect runs after rendering, causing UI flicker. Modern React encourages server components or framework-level data loading.
Quick Summary: useEffect data fetching creates a client-side waterfall: render → useEffect fires → fetch → re-render. In React 18+, the preferred pattern is fetching in Server Components (zero client cost), using data-fetching libraries like SWR or React Query, or using the new use hook. useEffect for fetching is also problematic in Strict Mode's double-fire behavior.
Q5:

What is the difference between batching in React 17 and React 18?

Junior

Answer

React 17 batched updates only inside React events. React 18 batches updates automatically in async operations like promises and timeouts.
Quick Summary: React 17 only batched state updates inside event handlers — updates in setTimeout or promises caused separate re-renders. React 18 introduced automatic batching: all state updates (in any context — timeouts, promises, native events) are batched together into one re-render. Fewer re-renders, better performance by default.
Q6:

Why does React warn when state is updated during rendering?

Junior

Answer

Updating state during render breaks render purity and creates infinite re-render loops.
Quick Summary: Updating state during rendering creates an infinite loop or at least unpredictable behavior — the render triggers a state update which triggers another render. React detects this pattern and warns because the render function must be a pure, side-effect-free function. State updates belong in event handlers or effects, not mid-render.
Q7:

What is the purpose of the useTransition hook?

Junior

Answer

useTransition marks certain state updates as non-urgent, keeping the UI responsive while React processes expensive updates in the background.
Quick Summary: useTransition marks a state update as non-urgent — it tells React "this update can be interrupted if something more important comes in." React renders the current UI immediately and updates the transition in the background. While pending, isPending is true so you can show a loading indicator. Great for search, filtering, and navigation.
Q8:

How does React decide which components to re-render?

Junior

Answer

React re-renders a component when its state or props change or when its parent re-renders. Siblings do not re-render unless their props change.
Quick Summary: When state or props change, React re-renders that component and, by default, all its children — even if the children's props didn't change. React.memo, useMemo, and useCallback help break this chain by bailing out of re-renders when inputs haven't changed. Without memoization, re-renders cascade down the entire subtree.
Q9:

Why must React state remain immutable?

Junior

Answer

React detects state changes using reference equality. Mutating state directly keeps the same reference, preventing React from re-rendering.
Quick Summary: React uses object identity to detect changes. If you mutate an object in place (array.push, obj.x = 1), the reference doesn't change — React thinks nothing changed and skips re-rendering. Always create new objects/arrays for state updates so React sees a new reference and knows to update the UI.
Q10:

What happens when state setters run inside loops outside event handlers?

Junior

Answer

It can trigger multiple renders or infinite loops because render must stay pure and deterministic.
Quick Summary: React 18 automatically batches multiple state updates into one re-render, even in timeouts and promises. State setters inside loops or outside event handlers are batched and applied together at the end. The component re-renders once with the final accumulated state, not once per update.
Q11:

What is the Render Prop pattern?

Junior

Answer

It is a technique where a component receives a function as a child to dynamically render UI, enabling reusable logic.
Quick Summary: Render Props pass a function as a prop — the parent component calls it with data, and the child renders whatever the function returns. It's a pattern for sharing stateful logic between components without HOCs. Largely replaced by custom hooks, which are cleaner and less nested, but still useful in some library APIs.
Q12:

What problem does React Context solve?

Junior

Answer

Context avoids prop drilling by allowing components to access shared data without passing props through every level.
Quick Summary: Context provides a way to share values (theme, user, locale) across the component tree without prop drilling — passing props through every intermediate component. It's ideal for truly global data that many components need. For complex state management or high-frequency updates, Redux or Zustand are often better choices.
Q13:

How does React Context differ from Redux?

Junior

Answer

Context provides simple global state but triggers broad re-renders. Redux offers structured state management, middleware, and optimized performance.
Quick Summary: Context is built into React and great for low-frequency global data (theme, auth state). Redux is a separate library with a global store, strict action-based updates, middleware support, and powerful devtools. Context re-renders all consumers on any value change; Redux lets components subscribe to specific slices.
Q14:

What does useReducer help solve?

Junior

Answer

useReducer manages complex state logic with multiple transitions or nested updates, offering a structured alternative to multiple useState hooks.
Quick Summary: useReducer is better than useState when state has multiple sub-values that change together, or when the next state depends on complex logic based on the previous state. It centralizes state transition logic in one place (the reducer), making it easier to reason about, test, and debug — especially when state updates involve multiple fields.
Q15:

Why should objects or arrays not be placed directly in dependency arrays?

Junior

Answer

Objects and arrays create new references every render, causing effects to re-run unnecessarily.
Quick Summary: Object and array literals create a new reference every render — even if the contents are the same. In a dependency array, React uses Object.is() to compare — a new reference always triggers the effect or memo. Memoize objects and arrays with useMemo, or use primitive values in dependency arrays when possible.
Q16:

What is memoization in React and when is React.memo useful?

Junior

Answer

React.memo caches rendered output and prevents re-renders when props have not changed, improving performance for stable components.
Quick Summary: React.memo wraps a component and skips re-rendering if props haven't changed (shallow comparison). Useful when a child component is expensive to render and its parent re-renders frequently. Not a silver bullet — only effective when props are actually stable, and shallow comparison matches your needs.
Q17:

What is the difference between useMemo and useCallback?

Junior

Answer

useMemo memoizes computed values, while useCallback memoizes function references.
Quick Summary: useMemo caches the result of a computation — returns the same value until dependencies change. useCallback caches a function reference — returns the same function until dependencies change. Use useMemo for expensive calculations you don't want to recompute on every render. Use useCallback to stabilize functions passed as props to memoized children.
Q18:

Why is lifting state up used in React?

Junior

Answer

Shared state must be managed in a common parent to keep child components synchronized.
Quick Summary: When two sibling components need to share state, move that state up to their common parent. The parent manages the state and passes it down as props. This keeps state in sync without global stores. It's the fundamental React pattern for sharing data — keep state as close to where it's needed as possible, but no lower.
Q19:

What are controlled inputs and why can they hurt performance?

Junior

Answer

Controlled inputs update React state on each keystroke, causing re-renders that may slow down long forms.
Quick Summary: Controlled inputs re-render the component on every keystroke because each character change updates state. In large forms with many fields, this cascades re-renders across the form. Solutions: debounce state updates, split into smaller components with React.memo, or use uncontrolled inputs with refs for inputs that don't need real-time validation.
Q20:

What is Suspense and why was it introduced?

Junior

Answer

Suspense lets components wait for async resources with a fallback UI. It supports streaming and async rendering.
Quick Summary: Suspense lets components declare they're waiting for something (data, code) by throwing a Promise. React catches the throw, shows a fallback UI (like a spinner), and resumes rendering when the Promise resolves. This makes async loading declarative — you don't need loading state variables scattered through your code.
Q21:

How does Suspense differ in data fetching vs code splitting?

Junior

Answer

For code splitting it waits for dynamic imports; for data fetching it waits for a Promise to resolve.
Quick Summary: For code splitting (React.lazy), Suspense catches the lazy import promise and shows a fallback while the chunk loads. For data fetching, Suspense catches a data-fetching promise thrown by the component — but this requires a Suspense-compatible data library (like SWR, React Query, or Server Components). The mechanism is the same; the integration differs.
Q22:

What is hydration in React?

Junior

Answer

Hydration attaches event listeners and React behavior to server-rendered HTML to make it interactive.
Quick Summary: Hydration attaches React's event handlers to server-rendered HTML so the page becomes interactive. The server sends HTML (fast first paint), and the client-side React code runs and "takes over" the DOM without re-rendering everything. If the client render doesn't match the server HTML, React warns about a hydration mismatch.
Q23:

What is partial hydration?

Junior

Answer

Only selected components are hydrated, reducing JavaScript execution and improving performance.
Quick Summary: Partial hydration means only interactive parts of the page are hydrated — static content stays as plain HTML with no JavaScript attached. This reduces the client-side JS work needed to make the page interactive. React 18's selective hydration (in Suspense boundaries) is a form of partial hydration — interactive islands are hydrated on demand.
Q24:

How does React handle synthetic events?

Junior

Answer

React attaches a single root event listener and normalizes events across browsers for consistency and performance.
Quick Summary: React uses a Synthetic Event system that wraps browser native events in a cross-browser compatible object. In React 17+, events are attached to the root DOM container (not document), making React embeds easier to manage alongside other libraries. Synthetic events normalize browser differences and support event delegation efficiently.
Q25:

What is useDeferredValue used for?

Junior

Answer

It returns a deferred version of a rapidly changing value, allowing heavy UI updates to lag behind typing.
Quick Summary: useDeferredValue accepts a value and returns a deferred (potentially stale) version of it. React renders the UI with the immediate value first, then re-renders with the deferred value when it has time. Useful for search inputs — the text field updates instantly, but the expensive filtered list updates slightly later without blocking input.
Q26:

How does React 19 improve hydration?

Junior

Answer

React 19 supports partial hydration, reduces long tasks, and hydrates server components more efficiently.
Quick Summary: React 19 makes hydration more resilient — it can recover from mismatches between server HTML and client render (previously it would log a warning and re-render the entire component). It also improves streaming hydration performance and handles third-party script interference in the DOM better.
Q27:

What is useOptimistic in React 19?

Junior

Answer

useOptimistic enables optimistic UI updates before server confirmation, improving perceived performance.
Quick Summary: useOptimistic in React 19 lets you immediately show the expected result of an action before the server confirms it. The UI updates optimistically (appears instant), and if the server action fails, React reverts to the previous state. Replaces manual optimistic update patterns that required extra useState and error handling.
Q28:

What is the difference between the use hook and await in React 19?

Junior

Answer

The use hook unwraps promises directly during rendering and pauses rendering until resolved, working in server components.
Quick Summary: The use hook in React 19 is a new primitive that reads the value from a Promise or Context inside components (including conditionally inside loops). Unlike await which blocks, use integrates with Suspense — the component suspends while waiting, and resumes when the Promise resolves. Works in both Server and Client Components.
Q29:

Why shouldn’t data fetching occur in constructors or render methods?

Junior

Answer

Fetching causes side effects. Render and constructors must remain pure, so fetching should occur in effects or server loaders.
Quick Summary: Constructors and render methods run synchronously and block painting. Fetching data there delays the initial render. It also causes bugs in concurrent mode where React may run render multiple times. Data fetching belongs in effects, server-side data loaders, or Suspense-compatible libraries that integrate with React's rendering lifecycle.
Q30:

What is an error boundary?

Junior

Answer

An error boundary catches runtime errors in child components and displays a fallback UI instead of crashing the entire app.
Quick Summary: Error boundaries are class components that catch JavaScript errors thrown by their children during rendering, in lifecycle methods, or in constructors. They prevent the whole app from crashing — instead, they render a fallback UI. You can't use hooks for this; class components with componentDidCatch are required.
Q31:

Why shouldn’t you mutate refs?

Junior

Answer

Refs are not reactive. Mutating them will not trigger re-renders, so using them to drive UI updates is ineffective.
Quick Summary: Refs hold a mutable container — mutating ref.current doesn't cause a re-render, which is why they're used for DOM access and imperative APIs. Mutating a ref that React uses internally (like a DOM node's style or children) can conflict with React's own DOM management, causing inconsistencies that are difficult to debug.
Q32:

What does useImperativeHandle do?

Junior

Answer

It customizes the instance value exposed to parent components when using refs, often exposing methods like focus().
Quick Summary: useImperativeHandle customizes what is exposed when a parent uses a ref on a child component. Instead of exposing the raw DOM node, you expose specific methods (like focus(), scrollTo()). Used with forwardRef, it gives you controlled, documented imperative API surface on components instead of leaking internal DOM references.
Q33:

What are custom hooks and why are they important?

Junior

Answer

Custom hooks extract reusable logic from components, making code cleaner, modular, and easier to maintain.
Quick Summary: Custom hooks extract reusable stateful logic from components into functions. Instead of duplicating useEffect + useState logic across multiple components, you write it once as useWindowSize or useAuthStatus and use it anywhere. They keep components clean and focused on rendering while the logic stays testable and composable.
Q34:

Why is having too many states in a component problematic?

Junior

Answer

Too many states cause unnecessary re-renders, tightly coupled logic, and reduced component reusability.
Quick Summary: Too many useState calls in one component usually mean the component does too many things. Each state update re-renders the entire component. Hard to reason about which state drives which behavior. Split into smaller components, group related state with useReducer, or move derived values to useMemo instead of storing them as separate state.
Q35:

Why do React 18+ and React 19 emphasize asynchronous rendering?

Junior

Answer

Async rendering prevents UI blocking during heavy updates, improving responsiveness and reducing jank.
Quick Summary: Modern apps need to handle slow networks, large data, and complex UIs without freezing. Synchronous rendering blocks the main thread — if rendering takes 200ms, the browser can't respond to user input. Async rendering (concurrent mode) lets React yield to the browser between chunks of work, keeping the app responsive.

Curated Sets for React

No curated sets yet. Group questions into collections from the admin panel to feature them here.

Ready to level up? Start Practice