52 questions - Beginner to advanced

React interview questions and answers

React interviews focus on three things: how state and props flow, what makes a component render again, and whether you know hooks well enough to avoid bugs. Answer with the reason, not only the API name.

Last updated:

React fundamentals

What is React?

React is a JavaScript library for building user interfaces out of components. You describe what the screen should look like for the current state. React then works out the smallest set of DOM changes needed to reach it.

What is JSX?

JSX is HTML-like syntax written inside JavaScript. A build tool turns every tag into a function call, so JSX is only a nicer way to describe elements. Because it becomes JavaScript, you write className instead of class, and event names in camelCase.

const el = <h1 className="title">Hello</h1>;
// becomes roughly:
// jsx("h1", { className: "title", children: "Hello" })

What is the virtual DOM?

The virtual DOM is a light copy of the UI kept in memory. When state changes, React builds a new copy, compares it with the old one, and applies only the differences to the real DOM. Touching the real DOM is slow, so this saves work.

What is reconciliation?

Reconciliation is React comparing the new element tree with the old one. If the element type is different, React throws the old subtree away and builds a new one. For lists, it uses keys to match children.

What is the difference between props and state?

Props come from the parent and are read-only inside the component. Only the parent can change them. State belongs to the component itself, is private, and changing it with the setter makes the component render again.

Why must you not modify state directly?

React compares old and new state by reference. If you change the same object, the reference stays the same, React sees nothing new, and the screen does not update. Always make a new object or array.

// wrong
items.push(newItem);
setItems(items);

// right
setItems([...items, newItem]);

What are keys in a list and why do they matter?

A key tells React which item is which between renders, so it can move DOM nodes instead of building them again. Use a stable unique id. The array index breaks when items are added, removed or reordered: inputs keep the wrong values and animations jump.

What is a controlled component?

A controlled input takes its value from React state and sends changes back through onChange. React is the one source of truth. An uncontrolled input keeps its value in the DOM and you read it with a ref, which is simpler but harder to validate while typing.

const [name, setName] = useState("");
<input value={name} onChange={(e) => setName(e.target.value)} />

What is a fragment?

A fragment groups several elements without adding a real DOM node. Write it as <>...</> or <React.Fragment>. Use the long form when you need a key, for example inside a list.

What is the difference between a class component and a function component?

A class component uses lifecycle methods and this.state. A function component is a plain function that uses hooks. Function components are the standard today: less code, no confusion with this, and logic is easier to share.

What is conditional rendering?

It means choosing what to render with normal JavaScript: a ternary, && or an early return. Be careful with && and numbers. 0 && <X/> puts 0 on the screen, so compare clearly instead.

{items.length > 0 && <List items={items} />}   // safe
{items.length && <List items={items} />}       // renders 0 when empty

What is prop drilling?

Prop drilling is passing a prop through several components that do not need it, only to reach a deep child. Fix it with Context, with composition by passing children, or with a state library. Do not reach for Context for every value.

Hooks

The heart of a modern React interview.

What are the rules of hooks?

Call hooks only at the top level of a component or of another hook. Never inside an if, a loop or a nested function. And call them only from React functions. React matches hooks to state by call order, so a hook inside a condition shifts everything.

How does useState work?

It returns the current value and a setter. Calling the setter schedules a new render. When the new value depends on the old one, pass a function, so you always read the latest value.

const [count, setCount] = useState(0);
setCount((c) => c + 1); // safe inside async code and batches

What is lazy initial state?

It means passing a function to useState, so the costly work runs only on the first render instead of on every render.

const [rows, setRows] = useState(() => parseBigJson(raw));

What does useEffect do?

It runs side effects after the render is painted: fetching data, subscriptions, timers, manual DOM work. The dependency array decides when it runs again. The function you return cleans up before the next run and when the component unmounts.

useEffect(() => {
  const id = setInterval(tick, 1000);
  return () => clearInterval(id);
}, []);

What is the difference between an empty array, no array and a filled array in useEffect?

No array: it runs after every render. An empty array: it runs once, after the first render. An array with values: it runs again whenever one of those values changes.

What is the most common useEffect mistake?

Missing dependencies, which makes the effect read old values. Next is forgetting cleanup, which leaks timers and listeners. A close third is using an effect to work out state that could simply be calculated during render.

What is the difference between useEffect and useLayoutEffect?

useEffect runs after the browser has painted, so it does not hold up the screen. useLayoutEffect runs right after the DOM update but before paint. Use it when you must measure an element and fix it before the user sees a flicker.

What is useRef used for?

Two things. Holding a reference to a DOM node. And keeping a value between renders that does not cause a new render when it changes, like a timer id or a previous value.

const inputRef = useRef(null);
useEffect(() => inputRef.current?.focus(), []);
<input ref={inputRef} />

What is the difference between useRef and useState?

Changing state renders the component again. Changing a ref does not. Use state for anything the UI shows. Use a ref for values you only read inside handlers and effects.

What is useMemo?

useMemo saves the result of a costly calculation and only runs it again when a dependency changes. It is also used to keep an object or array reference steady, so a memoised child does not render again.

const sorted = useMemo(
  () => [...items].sort((a, b) => a.price - b.price),
  [items]
);

What is useCallback?

useCallback returns the same function reference between renders while the dependencies stay the same. It helps only when that function is passed to a memoised child or used as an effect dependency.

When should you not use useMemo or useCallback?

When the work is cheap. They are not free. They use memory and run a comparison on every render, and they make the code noisier. Measure first, then optimise.

What is useReducer and when is it better than useState?

useReducer keeps state in one place and changes it through actions. It is better when several values change together, when the next state depends a lot on the previous one, or when the update logic is big enough to test on its own.

function reducer(state, action) {
  switch (action.type) {
    case "add": return { ...state, count: state.count + 1 };
    default: return state;
  }
}
const [state, dispatch] = useReducer(reducer, { count: 0 });

What is useContext?

It reads a value from the nearest Provider above it, so you can share data without prop drilling. Every consumer renders again when the provider value changes, so split contexts and memoise the value object.

const ThemeContext = createContext("light");

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Save</button>;
}

Is Context a replacement for Redux?

No. Context only passes a value down the tree. It has no reducers, no devtools, no middleware and no way to subscribe to one slice. It suits theme, language and the current user. Data that changes often is better in a state library.

What is a custom hook?

A custom hook is a function whose name starts with "use" and that calls other hooks. It lets you reuse logic, not markup. Every component that calls it gets its own separate state.

function useDebounced(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}

What is useId for?

useId makes a stable unique id that is the same on the server and on the client. It is the correct way to link a label to an input inside a reusable component, with no risk of two ids clashing.

What do useTransition and useDeferredValue do?

They mark an update as low priority, so React can keep the page responsive. useTransition wraps a state update. useDeferredValue keeps showing the old value while a heavy render happens in the background. Both help with large filtered lists.

Rendering and performance

What causes a component to re-render?

Its own state changed. Or a context it reads changed. Or its parent rendered again. Note that "props changed" is not a separate reason: props change because the parent rendered again.

What does React.memo do?

It skips rendering a component again when its props are shallowly equal to last time. It does nothing if you pass a new object, array or inline function on every render. That is why it works together with useMemo and useCallback.

What is batching in React?

Batching means React groups several state updates into one render. Since React 18 this happens everywhere, including inside promises and timers, not only in event handlers.

How do you fix a slow long list?

Virtualise it, so only the visible rows exist in the DOM. A library like react-window does this. Also memoise the row component and give it steady props and keys.

What is code splitting in React?

Code splitting means loading part of the JavaScript only when it is needed, with React.lazy and Suspense. It is usually done per route. It makes the first download smaller.

const Dashboard = lazy(() => import("./Dashboard"));

<Suspense fallback={<Spinner />}>
  <Dashboard />
</Suspense>

What is an Error Boundary?

An Error Boundary is a component that catches an error thrown while rendering its children and shows a fallback instead of a blank page. Today it must be a class component. It does not catch errors inside event handlers or async code.

What is Strict Mode and why do effects run twice?

In development, Strict Mode mounts a component, unmounts it and mounts it again. This shows you any missing cleanup. It happens only in development. If running twice breaks something, your effect needs a cleanup function.

What is a portal?

A portal renders a child into a different place in the DOM, usually document.body, but keeps it in the React tree. So context and events still work. It is the standard fix for modals and tooltips that must escape a parent with overflow: hidden.

createPortal(<Modal />, document.body);

What is the difference between CSR, SSR and SSG?

Client-side rendering sends an almost empty page and builds it in the browser. Server-side rendering builds the HTML for each request, so the first paint and SEO are better. Static site generation builds the HTML once at build time. It is the fastest, but it only suits content that is the same for everyone.

What is hydration?

Hydration is React on the client attaching event handlers to HTML that the server already sent. If the client markup does not match the server markup, you get a hydration mismatch warning. It usually comes from using dates, random values or window during render.

What are Server Components?

Server Components run only on the server and send their output to the client. They can read a database directly and send no JavaScript to the browser. They cannot use state or effects. You mix them with normal client components.

State, data and routing

How do you share state between two sibling components?

Move the state up to their nearest common parent. Pass the value down as a prop and the setter down as a callback. If that parent is far away, use context or a state library.

How do you fetch data in React?

In a small app: useEffect with fetch, plus loading and error state, and an AbortController for cleanup. In a real app: a data library such as React Query or SWR. It handles caching, retries, duplicate requests and refetching for you.

useEffect(() => {
  const c = new AbortController();
  fetch("/api/users", { signal: c.signal })
    .then((r) => r.json())
    .then(setUsers)
    .catch((e) => { if (e.name !== "AbortError") setError(e); });
  return () => c.abort();
}, []);

What is a race condition in data fetching and how do you avoid it?

The user types a new search quickly. The first slow response comes back after the second one, so the wrong results are shown. Fix it by aborting the earlier request, or by ignoring a response when the effect has already been cleaned up.

What is the difference between server state and client state?

Server state lives somewhere else. It can go out of date and needs caching and refetching. That is what React Query is for. Client state is only local, like whether a dropdown is open. Mixing both in one store makes both harder.

How does routing work in a React SPA?

A router library maps the URL to a component and changes the URL with the history API instead of reloading. The server must send index.html for every path. Otherwise a direct visit to a deep link returns a 404.

What is a protected route?

It is a wrapper component that checks whether the user is logged in. It either renders the page or sends the user to login. It usually remembers the URL the user wanted, so they land there after signing in.

What is the children prop and composition?

children is whatever you put between the opening and closing tags of a component. Passing components as children, instead of passing data down many levels, is often the simplest fix for prop drilling.

What is a higher-order component?

A higher-order component is a function that takes a component and returns a new one with extra behaviour. It was the old way to share logic. Custom hooks do the same job more clearly, so you now see HOCs mostly in older code.

What are render props?

A render prop is a function passed as a prop, so the child decides what to render with the data it gets. Like HOCs, custom hooks have mostly replaced this pattern.

How do you test a React component?

Use React Testing Library. Render the component and use it the way a user would. Find elements by visible text or by their role, then check what the user sees. Do not test internal state or implementation details.

What is the difference between React and a framework like Next.js?

React is only the view library. You put routing, data fetching and the build together yourself. Next.js is a framework built on React. It gives you file-based routing, server rendering, API routes and image optimisation out of the box.

Continue with another topic

Practise live

CrackInterviewAI listens to the live interview and gives a structured answer on screen for coding, system design, HR and project questions. Download for Windows.