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?▼
componentDidMount → useEffect(() => {}, []). componentDidUpdate → useEffect(() => {}, [deps]). componentWillUnmount → cleanup function returned from useEffect: useEffect(() => { return () => cleanup(); }, []). shouldComponentUpdate → React.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.