React Interview Questions
React Interview Questions
Section titled “React Interview Questions”Core Concepts
Section titled “Core Concepts”Q: What is the virtual DOM and why does React use it?
The virtual DOM is an in-memory representation of the real DOM. When state changes, React re-renders the virtual DOM, diffs it against the previous version (reconciliation), and applies only the minimal set of changes to the real DOM. This avoids costly full-page re-renders.
Q: What is the difference between controlled and uncontrolled components?
A controlled component has its value driven by React state — the input’s value prop is set from state, and onChange updates state. React is the single source of truth.
An uncontrolled component stores its own value in the DOM. You access the value via a ref rather than state. Simpler for one-off inputs but harder to validate or coordinate.
Q: What triggers a re-render?
- Component’s own state changes (
useState,useReducer) - Parent re-renders (even if props are identical)
- Context value changes
Q: What is reconciliation?
The algorithm React uses to diff the virtual DOM tree between renders to determine the minimum DOM updates needed. React assumes elements of different types produce different trees, and uses key props to match list items between renders.
Q: What rules apply to hooks?
- Only call hooks at the top level — not inside loops, conditions, or nested functions
- Only call hooks from React function components or other custom hooks
These rules ensure hooks are called in the same order on every render, which is how React tracks hook state.
Q: What is the difference between useEffect and useLayoutEffect?
useEffect runs asynchronously after the browser has painted. useLayoutEffect runs synchronously after DOM mutations but before the browser paints. Use useLayoutEffect when you need to measure DOM elements or prevent visual flickering — it blocks the paint.
Q: How do you prevent useEffect from running on every render?
Provide a dependency array. The effect only re-runs when those values change:
useEffect(() => { fetchUser(userId);}, [userId]); // only re-runs when userId changes
useEffect(() => { // runs once on mount}, []); // empty arrayQ: When would you use useReducer instead of useState?
When state logic is complex or involves multiple sub-values that change together. useReducer centralises state transitions in a pure reducer function, making transitions explicit and testable. Similar to how Redux works.
Q: What is the difference between useMemo and useCallback?
useMemomemoises a computed valueuseCallbackmemoises a function reference
const sorted = useMemo(() => [...items].sort(), [items]);const handleClick = useCallback(() => doSomething(id), [id]);Performance
Section titled “Performance”Q: How does React.memo work?
React.memo is a higher-order component that prevents re-rendering when the parent re-renders but props haven’t changed. It does a shallow comparison of props. If you pass objects or functions as props, you need useMemo / useCallback to stabilise their references.
Q: What causes unnecessary re-renders in Context?
Every component that calls useContext re-renders when the context value changes. If the provider computes the value object inline (value={{ theme, toggle }}), a new object is created on every render — causing all consumers to re-render even when nothing changed. Fix: memoize the value with useMemo.
State Management
Section titled “State Management”Q: When should you use Context vs a state management library?
Use Context for infrequently-updated global state (current user, theme, locale). For frequently updating state, or state with complex transitions, use Zustand or Redux Toolkit — they avoid the re-render cost of Context and provide better devtools.
Q: What is lifting state up?
Moving state to the closest common ancestor of components that need it, then passing it down as props. This is the fundamental pattern before reaching for Context or a state library.
Architecture
Section titled “Architecture”Q: What is the difference between presentational and container components?
A pattern (less rigidly applied with hooks today): presentational components receive data and callbacks as props and focus on rendering. Container components connect to data sources, fetch data, and pass it to presentational components. Hooks largely replace the need for separate container components.
Q: How do you handle errors in React?
Error boundaries catch errors in the render phase of child components:
class ErrorBoundary extends Component { state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
render() { if (this.state.hasError) return <h1>Something went wrong.</h1>; return this.props.children; }}For async errors (fetch failures), use try/catch in event handlers or effects.
Q: What is code splitting and how do you implement it in React?
Code splitting breaks the bundle into smaller chunks loaded on demand. Use React.lazy with Suspense:
const Dashboard = lazy(() => import('./Dashboard'));
<Suspense fallback={<Spinner />}> <Dashboard /></Suspense>The Dashboard module is downloaded only when first rendered.