React 18 · Updated March 2026

40+ React Interview
Questions & Answers (2026)

Interview questions actually asked at product companies and startups for React developer roles. Covers hooks, state, performance, lifecycle, and modern React patterns. By Deen Bandhu.

⏰ 20 min read 🎯 Freshers to 2 YOE ✅ React 18 💡 Code examples included

1. React Fundamentals

Q1.What is React and what problem does it solve?
React is a UI library (not a framework) for building component-based, declarative user interfaces. Problem it solves: DOM manipulation is slow and hard to manage at scale. React uses a Virtual DOM — diffs changes and updates only what changed in the real DOM — making large UIs fast and maintainable.
Q2.What is the Virtual DOM?
A lightweight in-memory copy of the real DOM. When state changes: React re-renders the virtual DOM, diffs it with the previous version (reconciliation), and only patches the minimum changes to the real DOM. This batching + minimal updates is what makes React fast. React 18 improves this with automatic batching.
Q3.What is JSX?
JSX is a syntax extension that looks like HTML inside JavaScript. Babel compiles JSX to React.createElement() calls. Rules: one root element (or Fragment <></>), use className not class, htmlFor not for, self-close empty tags, expressions in { }.
Q4.Props vs State — what's the difference?
Props: passed from parent to child, read-only (immutable), used to configure a component. State: local to the component, mutable via setState/setter, triggers re-render when changed. Rule: a component should never modify its own props. Use state for dynamic data, props for configuration.
Q5.What is a controlled vs uncontrolled component?
Controlled: form input's value is controlled by React state. You provide value and onChange. React is the "single source of truth". Uncontrolled: input manages its own value in the DOM. Access via useRef. Controlled is preferred — easier to validate, test, and synchronize.
Q6.What are keys in React lists and why are they important?
Keys help React identify which list items changed, were added, or removed during reconciliation. Without keys, React re-renders the entire list. Keys must be unique among siblings, stable (not array index if list can reorder), and not random. Use item.id from your data — never Math.random().

2. Hooks

Q7.What are React Hooks and why were they introduced?
Hooks let functional components use state and lifecycle features (previously class-only). Introduced in React 16.8 to: eliminate class boilerplate, reuse stateful logic (custom hooks), avoid this binding issues. Rules: only call at the top level (not inside loops/conditionals), only call from React functions.
Q8.Explain useState with an example.
const [count, setCount] = useState(0). Returns current value and a setter. Calling setter with a new value triggers re-render. Key gotchas: state updates are asynchronous (don't read state immediately after setting it); for state based on previous value use functional update: setCount(prev => prev + 1) — avoids stale closure bugs.
Q9.Explain useEffect — when does it run?
useEffect(callback, deps). Runs after render. Dependency array controls when: no array → runs after every render; empty array [] → runs once after mount (componentDidMount equivalent); with deps → runs when any dep changes. Return a cleanup function for subscriptions, timers, event listeners.
Q10.What is useRef?
Returns a mutable object { current: value } that persists across renders. Two uses: 1) DOM access — attach to element via ref prop (inputRef.current.focus()). 2) Store mutable value without triggering re-render — e.g. store previous value, timer ID, interval ID. Changing .current does NOT cause a re-render.
Q11.useCallback vs useMemo — difference?
useMemo: memoizes a computed value. Re-computes only when deps change. Use for expensive calculations. useCallback: memoizes a function reference. Returns same function instance when deps haven't changed. Use when passing callbacks to memoized children (React.memo) to prevent unnecessary re-renders. Don't overuse — they add overhead; profile first.
Q12.What is useContext?
Reads from a Context without prop drilling. const value = useContext(MyContext). Context re-renders all consumers when its value changes — watch out for performance. Split contexts by update frequency (separate AuthContext and ThemeContext). For complex state, combine with useReducer.
Q13.What is useReducer and when to use it over useState?
const [state, dispatch] = useReducer(reducer, initialState). Prefer useReducer when: state is an object with multiple sub-values, next state depends on previous state in complex ways, or you have many related state updates. Similar to Redux pattern — reducer is a pure function (state, action) => newState.
Q14.What are custom hooks?
Functions starting with use that encapsulate and reuse stateful logic. Examples: useFetch(url) for data fetching, useLocalStorage(key), useDebounce(value, delay). Custom hooks let you extract repetitive logic out of components — makes components cleaner and logic testable. Custom hooks can call other hooks.

3. State Management

Q15.When should you use Context API vs Redux?
Context API: good for low-frequency updates (theme, locale, auth user). Simple to set up, built-in. Redux: good for complex global state with many consumers, frequent updates, and when you need DevTools/time-travel debugging. Modern alternative: Zustand — minimal API, no boilerplate, great performance. For server state: use React Query or SWR.
Q16.What is prop drilling and how do you solve it?
Passing props through many intermediate components that don't need them. Solutions: Context API (for infrequent updates), component composition (pass components as children instead of data), state management library (Zustand, Redux). Component composition is often the simplest fix — underused solution.
Q17.What is React Query / TanStack Query?
Library for server state management — fetching, caching, synchronizing, and updating async data. Handles: loading/error states, caching with stale-while-revalidate, background refetch, pagination, optimistic updates. Eliminates 90% of useEffect+useState boilerplate for API calls. Highly recommended for any React app that talks to a backend.

4. Performance Optimization

Q18.What is React.memo?
HOC that memoizes a component — skips re-rendering if props haven't changed (shallow comparison). Use when a child component renders frequently and receives stable props. Must pair with useCallback for function props to be stable. Don't wrap every component — profile first, memoize only what's needed.
Q19.What is code splitting and lazy loading in React?
Split bundle into chunks loaded on demand. Use React.lazy() + Suspense: const Dashboard = React.lazy(() => import('./Dashboard')). Wrap with <Suspense fallback={<Spinner/>}>. Reduces initial bundle size — critical for performance. Combine with React Router to lazy-load routes.
Q20.How do you optimize a React app that re-renders too often?
1) Identify with React DevTools Profiler. 2) React.memo on expensive child components. 3) useCallback to stabilize function props. 4) useMemo for expensive computations. 5) Split Context so consumers only re-render when relevant data changes. 6) Virtualize long lists with react-window. 7) Move state down — don't lift state higher than necessary.
Q21.What is list virtualization?
Rendering only visible items in a long list instead of all items. A list of 10,000 items renders only the ~20 visible + buffer. Use react-window or react-virtual. Essential for performance when rendering large datasets — reduces DOM nodes from thousands to ~50.

5. Lifecycle & Effects

Q22.How do class lifecycle methods map to hooks?
componentDidMountuseEffect(() => {}, []). componentDidUpdateuseEffect(() => {}, [deps]). componentWillUnmount → cleanup function returned from useEffect: useEffect(() => { return () => cleanup(); }, []). shouldComponentUpdateReact.memo.
Q23.What is the cleanup function in useEffect?
Return a function from useEffect to clean up side effects when component unmounts or before the effect re-runs. Use for: clearing timers (clearInterval/clearTimeout), removing event listeners, cancelling subscriptions (WebSocket, API with AbortController). Without cleanup: memory leaks and "setState on unmounted component" errors.
Q24.What is a stale closure in useEffect?
When a useEffect callback captures an outdated value of a variable from its closure. Common bug: a timer or interval inside useEffect uses the initial state value, never the updated one. Fix: include the variable in dependency array, or use useRef to store the latest value, or use the functional update form of setState.

6. Patterns & Best Practices

Q25.What is the component composition pattern?
Building flexible UIs by composing components instead of configurating them with many props. Use children prop or named slots. Example: <Card header={<Title/>} footer={<Actions/>}>content</Card> instead of <Card title="..." actions={...}>. Avoids prop drilling and creates open/closed components.
Q26.What are Higher Order Components (HOCs)?
Function that takes a component and returns a new component with added behavior. Example: withAuth(Component) wraps Component and redirects to login if not authenticated. HOCs were the pre-hooks pattern for logic reuse. Today, custom hooks are preferred — simpler, no wrapper hell, easier to compose.
Q27.What is Error Boundary?
Class component that catches JavaScript errors in its child component tree and displays a fallback UI instead of crashing the whole app. Implement componentDidCatch and getDerivedStateFromError. Note: Error Boundaries don't catch errors in event handlers or async code (use regular try-catch there). React 18: use the react-error-boundary library for hooks-friendly version.

7. React 18 Features

Q28.What is Automatic Batching in React 18?
React 18 batches multiple setState calls into one render — even in async functions, event handlers, and promises. React 17 only batched inside React event handlers. Means fewer re-renders with no code change. To opt out of batching for a specific update, use ReactDOM.flushSync().
Q29.What is the useTransition hook?
Marks a state update as non-urgent — React can interrupt it to handle more urgent updates (like user input). const [isPending, startTransition] = useTransition(). Use for slow, non-urgent UI updates (filtering a large list). The urgent update (typing) stays responsive while the transition (filtered results) renders in background.
Q30.What is React Suspense?
Lets components "wait" for something (lazy load, data fetch) and show a fallback while waiting. <Suspense fallback={<Loading/>}><LazyComponent/></Suspense>. React 18 extends Suspense to data fetching with frameworks like Next.js and React Query. Enables streaming SSR with renderToPipeableStream.
React 2026React HooksuseStateuseEffect React PerformanceReact 18FrontendFreshers
// AlgoVentra — Java Full Stack (React + Spring Boot)

Learn React + Spring Boot Together

AlgoVentra's Full Stack course covers React and Spring Boot — you build a complete full stack app with JWT auth, REST APIs, and a deployed React frontend.