React is a JavaScript library for building user interfaces, developed by Meta. These questions cover core concepts, hooks, performance, state management, and advanced patterns commonly tested in frontend developer interviews.
React is a declarative, component-based JavaScript library for building UIs. It solves the problem of efficiently updating and rendering the right components when data changes, using a virtual DOM to minimize expensive real DOM operations.
Class components use ES6 classes, have lifecycle methods, and historically managed state via this.state. Functional components are plain JavaScript functions that are simpler, easier to test, and since React 16.8 can use hooks to handle state and side effects, making class components largely unnecessary.
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. Babel transpiles it to React.createElement() calls, making component trees easier to read and write than raw function calls.
The virtual DOM is a lightweight in-memory representation of the real DOM. When state or props change, React creates a new virtual DOM tree, diffs it against the previous one (reconciliation), and applies only the minimal set of real DOM mutations needed.
Props are read-only inputs passed from a parent component to a child, while state is mutable data managed internally by a component. Props flow down the component tree; state changes trigger re-renders of the component that owns it and its descendants.
useState is a hook that adds local state to a functional component. It returns a tuple of the current state value and a setter function; calling the setter schedules a re-render with the new value.
useEffect lets you perform side effects (data fetching, subscriptions, DOM manipulation) after render. It accepts a callback and an optional dependency array; the effect re-runs only when listed dependencies change, and you can return a cleanup function to avoid memory leaks.
Keys are stable, unique identifiers attached to list items that help React's reconciler identify which items changed, were added, or removed. Without proper keys, React may re-render or reorder elements incorrectly, causing bugs and performance issues.
useCallback memoizes a function reference so it is only recreated when its dependencies change. Use it when passing callbacks to child components wrapped in React.memo to prevent unnecessary re-renders caused by new function references on every render.
useMemo memoizes the return value of a computation, while useCallback memoizes the function itself. Use useMemo for expensive derived values; use useCallback for stable function references.
React.memo is a higher-order component that shallowly compares a functional component's props; if they haven't changed, the component skips re-rendering. You can supply a custom comparison function as a second argument for deeper control.
Context API provides a way to share values (theme, locale, auth) across the component tree without prop drilling. Prefer it for low-frequency, globally needed data; for complex, high-frequency state with many derived values and actions, a dedicated library like Redux or Zustand offers better devtools and performance optimizations.
useRef returns a mutable object whose .current property persists across renders without triggering re-renders. Common uses include accessing DOM nodes directly (focus, measurements), storing previous state values, and holding mutable instance variables like timers.
Code splitting breaks your bundle into smaller chunks loaded on demand, reducing initial load time. In React, you implement it with React.lazy() paired with a Suspense boundary, or via dynamic import() in routing libraries like React Router.
Reconciliation is React's algorithm for diffing the previous and new virtual DOM trees to determine the minimum number of real DOM changes. React applies heuristics such as comparing element types and using keys to keep the process efficient at O(n) rather than O(n³).
Portals let you render a component's output into a different DOM node outside the parent component's hierarchy, while React event bubbling still works normally. Typical use cases include modals, tooltips, and dropdowns that must escape overflow:hidden or z-index constraints.
useReducer manages state via a (state, action) => newState reducer function, similar to Redux. Prefer it over useState when state logic is complex (multiple sub-values, next state depends on previous), or when the same state needs to be updated in several different ways.
Concurrent React allows React to interrupt, pause, and resume rendering work, so it can keep the UI responsive during expensive updates. Features like startTransition mark updates as non-urgent, and Suspense with streaming SSR improves time-to-interactive by showing content progressively.
RSCs render entirely on the server and send serialized UI (not JavaScript) to the client, reducing bundle size and enabling direct data-layer access without round trips. Unlike client components, they cannot use browser APIs, hooks, or event handlers, and they never re-render on the client.
Key strategies include wrapping pure components with React.memo, stabilizing callbacks with useCallback and derived values with useMemo, lifting state appropriately to avoid broad context re-renders, splitting context into smaller slices, and using state management libraries that support selector-based subscriptions (e.g., Zustand, Recoil).
© RM Full Stack & AI Engineer · All interview questions · Roadmaps · Open the app