Skip to content

Repository files navigation

Top React.js Interview Questions (Updated for 2026)

Updated for 2026! Curated top React.js interview questions with high quality answers for acing your Front End Engineer interviews, brought to you by GreatFrontEnd.

Looking for more? Read our blog post 100+ React interview questions and answers compiled from ex-FAANG interviewers, including React 19 coverage (Actions, Server Components, the use hook, and the React Compiler).



Table of Contents

No. Questions
1 What is React? Describe the benefits of React
2 What is the difference between React Node, React Element, and a React Component?
3 What is JSX and how does it work?
4 What is the difference between state and props in React?
5 What is the purpose of the key prop in React?
6 What is the consequence of using array indices as the value for keys in React?
7 What is the difference between controlled and uncontrolled React components?
8 What are some pitfalls about using context in React?
9 What are the benefits of using hooks in React?
10 What are the rules of React hooks?
11 What is the difference between useEffect and useLayoutEffect in React?
12 What is the purpose of callback function argument format of setState() in React and when should it be used?
13 What does the dependency array of useEffect affect?
14 What is the useRef hook in React and when should it be used?
15 What is the useCallback hook in React and when should it be used?
16 What is the useMemo hook in React and when should it be used?
17 What is the useReducer hook in React and when should it be used?
18 What is the useId hook in React and when should it be used?
19 What does re-rendering mean in React?
20 What are React Fragments used for?
21 What is forwardRef() in React used for?
22 How do you reset a component's state in React?
23 Why does React recommend against mutating state?
24 What are error boundaries in React for?
25 How do you test React applications?
26 Explain what React hydration is
27 What are React Portals used for?
28 How do you debug React applications?
29 What is React Strict Mode and what are its benefits?
30 How do you localize React applications?
31 What is code splitting in a React application?
32 How would one optimize the performance of React contexts to reduce rerenders?
33 What are higher-order components in React?
34 What is the Flux pattern and what are its benefits?
35 Explain one-way data flow of React and its benefits
36 How do you handle asynchronous data loading in React applications?
37 Explain server-side rendering of React applications and its benefits
38 Explain static generation of React applications and its benefits
39 Explain the presentational vs container component pattern in React
40 What are some common pitfalls when doing data fetching in React?
41 What are render props in React and what are they for?
42 What are some React anti-patterns?
43 How do you decide between using React state, context, and external state managers?
44 Explain the composition pattern in React
45 What is virtual DOM in React?
46 How does virtual DOM in React work? What are its benefits and downsides?
47 What is React Fiber and how is it an improvement over the previous approach?
48 What is reconciliation in React?
49 What is React Suspense and what does it enable?
50 Explain what happens when the useState setter function is called in React

Questions with answers

  1. What is React? Describe the benefits of React

    React is an open-source library maintained by Meta and the community for building user interfaces from components. Components describe UI declaratively from props, state, and context; React reconciles those descriptions and commits the necessary changes through renderers such as React DOM and React Native. Its main benefits are composability, explicit one-way data flow, reusable stateful logic through Hooks, support for client and server rendering architectures, and a broad ecosystem.

    Key characteristics of React:

    • Declarative: You describe the desired UI from data, and the renderer coordinates the required host updates.
    • Component-based: Build reusable and modular UI elements (components) that manage their own state and logic.
    • Reconciliation: React compares element descriptions and commits the necessary renderer-specific changes. These descriptions are not a copy of the browser DOM.
    • JSX: While not mandatory, JSX is a syntax extension for expressing element structure alongside JavaScript values and control flow.

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  2. What is the difference between React Node, React Element, and a React Component?

    A React Node is a value React can render, including an element, string, number, bigint, iterable of nodes, portal, or an empty value such as null or a boolean. React 19's type also supports promises that resolve to renderable nodes in supported rendering environments. A React Element is the immutable object produced by JSX or createElement that describes what to render. A React Component is a function or class React uses as an element type. Components produce nodes; elements are descriptions; nodes are the broader set of renderable values.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  3. What is JSX and how does it work?

    JSX is a syntax extension for JavaScript that lets you describe UI with HTML-like markup inside JavaScript. A build tool transforms it into ordinary function calls before the browser runs it. With the modern automatic runtime, <div>Hello, world!</div> becomes a call to a helper from react/jsx-runtime; the older classic transform used React.createElement.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  4. What is the difference between state and props in React?

    State is data a component owns and can update over time; props are data a component receives from its parent and must treat as read-only. A state update schedules the owning component to render again unless React can apply a same-value bailout; descendants render by default but may also bail out. New props arrive when the parent renders new element descriptions. Together they implement React's one-way data flow: state lives at the lowest common ancestor that needs it, flows down as props, and changes flow back up via callbacks passed as props.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  5. What is the purpose of the key prop in React?

    The key prop tells React how to identify each child in a list across renders so it can match the right component instance to the right data, preserve its state, and reorder DOM nodes correctly. A key only needs to be unique among siblings, not globally. Changing a component's key is also the idiomatic way to reset its state — React unmounts the old instance and mounts a fresh one.

    <ul>
      {items.map((item) => (
        <ListItem key={item.id} value={item.value} />
      ))}
    </ul>

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  6. What is the consequence of using array indices as the value for keys in React?

    Using array indices as keys causes React to reconcile the list incorrectly when items are reordered, inserted, or removed. Because the key identifies a position rather than an item, React reuses the wrong component instances — leaving stale local state, focus, and DOM attached to the wrong rows. The fix is to use a stable, unique identifier from the data (e.g. item.id). Index keys are only safe when the list is static and never reordered, filtered, or prepended to.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  7. What is the difference between controlled and uncontrolled React components?

    A controlled component drives a form input from React state — you pass value/checked plus an onChange handler, and React state is the single source of truth. An uncontrolled component lets the DOM keep the value; you read it via a ref (or on submit) and seed the initial value with defaultValue/defaultChecked. Controlled inputs are the right default when you need validation, conditional UI, or to derive other state from the value. Uncontrolled inputs are simpler for write-once forms and for <input type="file">, which is always uncontrolled. React 19 also added first-class form support via the form action prop, useFormStatus, and useActionState, which often removes the need for per-field controlled state.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  8. What are some pitfalls about using context in React?

    Context in React is convenient but easy to misuse. The biggest pitfalls are passing a fresh object or array as the provider value on every render, assuming memo or React Compiler will stop a context subscription update (they won't), and putting frequently changing, unrelated data into one context. Split independent values into focused providers, stabilize object values when appropriate, and consider a selector-based state library when consumers need different slices of rapidly changing state.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  9. What are the benefits of using hooks in React?

    Hooks let function components use state, context, refs, effects, and other React features without classes. Custom Hooks compose reusable stateful logic without adding wrapper components. React 19 added Hooks such as useActionState and useOptimistic, while React DOM provides useFormStatus. React 19's similarly named use(resource) is an API rather than a Hook and follows different call-order rules.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  10. What are the rules of React hooks?

    React hooks have a few essential rules to ensure they work correctly. Call hooks at the top level of a function component or custom hook — never inside loops, conditions, nested functions, or after an early return. The use API is the exception: it is not a Hook and may be called conditionally or in loops, but it must still run inside a component or Hook and cannot be wrapped in try/catch. Lean on eslint-plugin-react-hooks to enforce these rules.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  11. What is the difference between useEffect and useLayoutEffect in React?

    Both hooks run side effects after render, but they differ in when they fire relative to paint:

    • useEffect runs after React commits. For effects not caused by an interaction, React generally lets the browser paint first; interaction-driven effects may run before paint. Use it for synchronizing with external systems when the work does not need to block paint.
    • useLayoutEffect runs synchronously during the commit phase, after DOM mutations but before the browser paints. It blocks paint, so use it only when you need to measure the DOM and write to it in the same frame to avoid a visual flicker.

    Both accept a dependency array with the same semantics. In development Strict Mode, React performs an extra setup-and-cleanup cycle before the real setup. Neither effect runs during server rendering; useLayoutEffect is especially unsuitable there because the server has no layout to measure.

    Code example:

    import { useEffect, useLayoutEffect, useRef } from 'react';
    
    function Example() {
      const ref = useRef(null);
    
      useEffect(() => {
        console.log('useEffect: runs after paint');
      }, []);
    
      useLayoutEffect(() => {
        console.log('useLayoutEffect: runs before paint');
        console.log('Element width:', ref.current.offsetWidth);
      }, []);
    
      return <div ref={ref}>Hello</div>;
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  12. What is the purpose of callback function argument format of setState() in React and when should it be used?

    The callback (or updater function) form of setState — both this.setState(prev => ...) in classes and setX(prev => ...) with useState — guarantees that each update is computed from the latest queued state rather than the value captured in your closure. Use it whenever the next state depends on the previous state, especially when you call the setter more than once in the same event handler or when the update may run after an await/timeout/promise.

    import { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0);
    
      function handleClick() {
        setCount((value) => value + 1);
        setCount((value) => value + 1);
      }
      return <button onClick={handleClick}>{count}</button>;
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  13. What does the dependency array of useEffect affect?

    The dependency array of useEffect controls when React re-synchronizes the effect. With no array, React runs setup after every commit. With [], it runs setup after the component mounts (development Strict Mode immediately performs an extra setup/cleanup cycle). With dependencies, it runs after mount and again whenever any dependency changes according to Object.is. Cleanup runs before re-synchronization and after unmounting.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  14. What is the useRef hook in React and when should it be used?

    The useRef hook in React is used to create a mutable object that persists across renders. It can be used to access and manipulate DOM elements directly, store mutable values that do not cause re-renders when updated, and keep a reference to a value without triggering a re-render. For example, you can use useRef to focus an input element:

    import { useEffect, useRef } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null);
    
      useEffect(() => {
        inputEl.current?.focus();
      }, []);
    
      return <input ref={inputEl} type="text" />;
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  15. What is the useCallback hook in React and when should it be used?

    useCallback caches a function definition while its dependencies remain Object.is-equal. The point is referential stability — so a memo-wrapped child can skip a render, or an Effect that depends on the function does not re-synchronize unnecessarily. Creating a function literal is usually not the cost worth optimizing; use useCallback when the changing identity causes measured or semantically required downstream work.

    const memoizedCallback = useCallback(() => {
      doSomething(a, b);
    }, [a, b]);

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  16. What is the useMemo hook in React and when should it be used?

    useMemo caches a calculation result between renders while its dependencies remain Object.is-equal. Use it as a performance optimization for a measured expensive calculation or when a stable object/array identity enables another optimization. It is not a semantic guarantee, so code must remain correct if React discards the cache and recomputes the value. React Compiler can provide equivalent memoization for compatible code when the optional build-time optimizer is enabled.

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  17. What is the useReducer hook in React and when should it be used?

    The useReducer hook in React is used for managing complex state logic in functional components. It is an alternative to useState and is particularly useful when the state has multiple sub-values or when the next state depends on the previous one. It takes a reducer function and an initial state as arguments and returns the current state and a dispatch function.

    const [state, dispatch] = useReducer(reducer, initialState);

    Use useReducer when you have complex state logic that involves multiple sub-values or when the next state depends on the previous state.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  18. What is the useId hook in React and when should it be used?

    useId (added in React 18) generates a stable, unique string ID per component instance, per React root. Its main reason for existing is to produce IDs that match between the server-rendered HTML and the client hydration — a plain incrementing counter would produce mismatches. Within a single root the IDs are unique, but two separate roots on the same page can collide unless you set identifierPrefix on createRoot / hydrateRoot. Use it for things like linking <label htmlFor> to <input id>, never as a list key.

    import { useId } from 'react';
    
    function NameField() {
      const id = useId();
      return (
        <div>
          <label htmlFor={id}>Name:</label>
          <input id={id} type="text" />
        </div>
      );
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  19. What does re-rendering mean in React?

    A re-render means React calls a function component again (or calls a class component's render) to compute a new element description. State updates, context changes, or a parent rendering can trigger it. React then reconciles the result with the previous tree. Re-rendering is not the same as updating the DOM: if the rendered output is unchanged, the commit may perform no DOM mutations.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  20. What are React Fragments used for?

    React Fragments are used to group multiple elements without adding extra nodes to the DOM. This is useful when you want to return multiple elements from a component's render method without wrapping them in an additional HTML element. You can use the shorthand syntax <>...</> or the React.Fragment syntax.

    return (
      <>
        <ChildComponent1 />
        <ChildComponent2 />
      </>
    );

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  21. What is forwardRef() in React used for?

    As of React 19 (December 2024), forwardRef() is no longer necessary — function components can now accept ref as a regular prop, so wrapping in forwardRef() is no longer required. React plans to deprecate forwardRef() in a future release. forwardRef() historically existed because, before React 19, function components could not receive a ref prop and forwardRef() was the official workaround for forwarding a parent's ref down to a child DOM node or component.

    // Modern (React 19+): ref is a regular prop
    function MyInput({ ref, ...props }) {
      return <input ref={ref} {...props} />;
    }
    
    // Legacy (React 18 and earlier): wrap with forwardRef
    import { forwardRef } from 'react';
    const MyInputLegacy = forwardRef((props, ref) => (
      <input ref={ref} {...props} />
    ));

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  22. How do you reset a component's state in React?

    The most idiomatic way to reset a component's state in React is to give the component a key prop and change it — React unmounts the old instance and mounts a fresh one with brand-new state. For finer-grained resets, call your useState setter with the initial value, or dispatch a RESET action when using useReducer.

    // Force a full reset by changing the key
    <Form key={formId} />;
    
    // Or reset specific state in place
    setState(initialState);

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  23. Why does React recommend against mutating state?

    React treats state as a read-only snapshot. Mutating an object or array in place keeps the same reference, so an Object.is state bailout, memoized child, memoized calculation, or Effect dependency may not observe a change. Mutation also alters older render snapshots that still reference the object, making behavior harder to reason about and incompatible with features that rely on snapshot semantics. Produce a new object or array with spreads, non-mutating methods such as map/filter/toSorted, or a helper such as Immer.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  24. What are error boundaries in React for?

    Error boundaries catch errors thrown while rendering their descendant tree and display fallback UI instead of losing the entire React root. They are class components that use static getDerivedStateFromError to render a fallback and may use componentDidCatch for logging. Place them at meaningful recovery boundaries such as routes or independent panels. They do not catch event-handler errors, errors in arbitrary asynchronous callbacks, server-rendering errors, or errors thrown by the boundary itself. React has no function-component API for defining a boundary; a library can provide a reusable boundary component. React 19 also provides root options for reporting caught, uncaught, and recoverable errors, but those reporting callbacks do not replace fallback UI.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  25. How do you test React applications?

    A common stack is Jest or Vitest as the test runner with React Testing Library, which encourages testing observable behavior instead of implementation details. Drive realistic interactions with @testing-library/user-event, mock network calls with a tool such as MSW, and cover critical flows in a real browser with Playwright or Cypress. Use async queries (findBy*, waitFor) for UI that appears after asynchronous client updates. Test Server Components through the integration facilities of the framework and bundler that implement them.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  26. Explain what React hydration is

    Hydration is the process in which React renders the client tree, matches it to HTML previously produced by React on the server, attaches event handling, and makes the existing markup interactive. Use hydrateRoot rather than creating a fresh client root over server HTML. The first client output must match the server output; mismatches are bugs unless they are deliberately and narrowly suppressed.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  27. What are React Portals used for?

    React Portals are used to render children into a DOM node that exists outside the hierarchy of the parent component. This is useful for scenarios like modals, tooltips, and dropdowns where you need to break out of the parent component's overflow or z-index constraints. You create a portal with createPortal(child, container) from react-dom. Even though the rendered DOM lives elsewhere, the portal still belongs to the React tree, so events bubble up to the React parent and context still flows through normally.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  28. How do you debug React applications?

    Use React Developer Tools to inspect the component tree and profile commits, browser breakpoints and network tools for runtime behavior, and development Strict Mode to expose impure rendering and missing cleanup. Owner stacks help trace which component created failing JSX. React 19.2 also adds React tracks to Chrome performance profiles for scheduler and component work. Use error boundaries for render failures, while handling event and asynchronous errors at their source.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  29. What is React Strict Mode and what are its benefits?

    <StrictMode> enables development-only checks for a React subtree. React renders components an extra time to expose impure rendering, runs an extra setup-and-cleanup cycle for Effects, re-runs ref callbacks, and checks for deprecated APIs. It renders no UI and adds no production behavior. The extra work is a stress test: fix the missing cleanup or impurity instead of trying to suppress it.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  30. How do you localize React applications?

    To localize a React application, you typically use a library like react-i18next or react-intl. First, you set up your translation files for different languages. Then, you configure the localization library in your React app. Finally, you use the provided hooks or components to display localized text in your components.

    // Example using react-i18next
    import { useTranslation } from 'react-i18next';
    
    const MyComponent = () => {
      const { t } = useTranslation();
      return <p>{t('welcome_message')}</p>;
    };

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  31. What is code splitting in a React application?

    Code splitting in a React application is a technique used to improve performance by splitting the code into smaller chunks that can be loaded on demand. This helps in reducing the initial load time of the application. You can achieve code splitting using dynamic import() statements or React's React.lazy and Suspense.

    import { lazy, Suspense } from 'react';
    
    const LazyComponent = lazy(() => import('./LazyComponent'));
    
    function App() {
      return (
        <Suspense fallback={<div>Loading...</div>}>
          <LazyComponent />
        </Suspense>
      );
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  32. How would one optimize the performance of React contexts to reduce rerenders?

    Context consumers re-render whenever the provider receives a different value according to Object.is. Neither memo nor React Compiler prevents that subscription update. Keep provider values stable, split unrelated or differently changing data into separate contexts, and separate state from a stable dispatch function so dispatch-only consumers do not re-render on state changes. Use memo to protect expensive descendants below a consumer, and consider selector-based state libraries when consumers need independent slices of frequently changing state.

    const value = useMemo(() => ({ state, dispatch }), [state, dispatch]);

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  33. What are higher-order components in React?

    Higher-order components (HOCs) in React are functions that take a component and return a new component with additional props or behavior. They are used to reuse component logic. For example, if you have a component MyComponent, you can create an HOC like this:

    const withExtraProps = (WrappedComponent) => {
      return (props) => <WrappedComponent {...props} extraProp="value" />;
    };
    
    const EnhancedComponent = withExtraProps(MyComponent);

    HOCs were especially common before Hooks and remain valid in existing code and library APIs such as React Redux's connect. For new function components, custom Hooks usually share stateful logic with less wrapper nesting. An HOC can still be appropriate when the abstraction must return a component or wrap rendering rather than only share logic.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  34. What is the Flux pattern and what are its benefits?

    Flux is a historical application architecture Facebook introduced for managing state around React. An action goes through a central dispatcher to registered stores; stores update their own domain state, emit changes, and views render the new state. This unidirectional flow makes the source of an update easier to trace and separates event creation, state transitions, and rendering. The original Flux library is archived, and modern applications usually choose reducers, external stores, or server-state caches according to their needs rather than implementing classic Flux.

    • Core components:
      • Dispatcher: Single hub that manages actions and dispatches them to all registered stores.
      • Stores: Hold the state and business logic; act as change emitters that notify subscribed views.
      • Actions: Plain payloads of information sent from the application to the dispatcher.
      • View: React components that subscribe to stores and re-render when stores emit changes.
    • Benefits:
      • Predictable state management due to unidirectional data flow.
      • Explicit ownership of each domain's state.
      • Improved debugging and testing.
      • Clear separation of concerns.

    Example flow:

    1. User interacts with the View.
    2. Actions are triggered and dispatched by the Dispatcher.
    3. Stores process the actions, update their state, and emit a change event.
    4. View re-renders based on the updated state.

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  35. Explain one-way data flow of React and its benefits

    In React, one-way data flow means that data moves from parent components to children through props and context. Children treat those inputs as read-only; to request a parent-state change, a child invokes a callback or dispatch function supplied from above. Controlled inputs may look like two-way binding, but they still update through an explicit event followed by a new value flowing down. The benefits are explicit ownership, predictable updates, and easier tracing and testing.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  36. How do you handle asynchronous data loading in React applications?

    Prefer a framework's data-loading APIs when they can coordinate route requests before rendering, or a client cache such as TanStack Query, SWR, or RTK Query when browser-owned data needs caching and synchronization. Exact deduplication, retries, and refetch behavior depend on the tool and configuration. Fetching in an Effect remains valid for simple client-only cases, but it needs explicit loading/error handling, cleanup, and stale-response protection. React 19's use API can read a cached promise and suspend; the promise should come from a Suspense-enabled framework/cache, a route loader, or a Server Component rather than being recreated during render.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  37. Explain server-side rendering of React applications and its benefits

    Server-side rendering (SSR) renders React output to HTML on the server and sends it to the browser. hydrateRoot then attaches React to matching client-rendered output so interactive Client Components can work. Modern React streams with renderToPipeableStream for Node streams or renderToReadableStream for Web Streams. React 19.2 supports Web Streams in Node too, although the React team recommends Node streams there for performance. Benefits include earlier content and crawlable HTML; tradeoffs include server work, hydration cost, and mismatch risk.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  38. Explain static generation of React applications and its benefits

    Static generation (SSG) renders HTML ahead of requests, usually during a build, so the result can be cached and served from a CDN. React itself provides static rendering APIs, while frameworks decide how routes, data caches, and revalidation work. In Next.js, generateStaticParams can enumerate dynamic routes to prerender, but current caching is explicit rather than every fetch being static by default. SSG is best for content that does not vary per request; framework features such as revalidation and partial prerendering can combine cached shells with fresher content.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  39. Explain the presentational vs container component pattern in React

    The presentational vs container component pattern (also known as "dumb vs smart components") splits components into two roles: presentational components decide how things look and receive everything via props, while container components decide how things work — they fetch data, hold state, and pass props down. Dan Abramov, who popularized the pattern in 2015, updated his original article in 2019 to say he no longer recommends splitting components this way: hooks (especially custom hooks) cover the same separation of concerns without forcing you to introduce a wrapper component. The vocabulary is still useful for talking about responsibilities, but in modern React the "container" layer is usually a custom hook.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  40. What are some common pitfalls when doing data fetching in React?

    Common data-fetching pitfalls include missing loading and error states, ignoring HTTP error statuses, leaving stale requests active, allowing responses to win races, recreating promises during render, and triggering request waterfalls. Prefer framework loaders or a client cache when they fit. For manual Effect-based fetching, clean up with AbortController and handle Strict Mode's extra development setup/cleanup cycle. React 19's use API can read a cached promise with Suspense, but it does not make an ordinary fetch() created during render safe.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  41. What are render props in React and what are they for?

    Render props in React are a technique for sharing code between components using a prop whose value is a function. The component calls that function with some internal state or data, and the function returns the React element to render. The prop does not have to be named render — passing a function as children is the more common modern form.

    import { useState } from 'react';
    
    function Toggle({ children }) {
      const [on, setOn] = useState(false);
      return (
        <>
          <button onClick={() => setOn((value) => !value)}>Toggle</button>
          {children(on)}
        </>
      );
    }
    
    <Toggle>{(on) => <p>{on ? 'On' : 'Off'}</p>}</Toggle>;

    Render props were popular before hooks. As of modern React, custom hooks have largely replaced them for sharing stateful logic, though render props are still useful for components that own a piece of UI structure (e.g. virtualized lists, headless component libraries).


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  42. What are some React anti-patterns?

    React anti-patterns are practices that lead to inefficient, buggy, or hard-to-maintain code. Common ones in modern (hooks-era) React include:

    • Mutating state directly instead of producing a new value
    • Using useState to mirror props or other state instead of computing the value during render
    • Using useEffect to derive data that could just be computed
    • Using array index as key for dynamic lists
    • Stale closures inside effects (missing or wrong dependencies)
    • Forgetting to clean up effects (subscriptions, timers, listeners)
    • Mutating refs during render
    • Not using keys in lists at all
    • Reaching for useMemo/useCallback everywhere instead of where they actually help

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  43. How do you decide between using React state, context, and external state managers?

    Match the tool to the kind of state. Use useState/useReducer for local component state, and lift state up before reaching for anything heavier. Context transports a value through a subtree; it does not provide storage, update logic, or fine-grained subscriptions by itself. Reach for a client-state library such as Zustand, Jotai, or Redux Toolkit when many unrelated components need shared state and selector-based subscriptions or store tooling. Treat server state separately: a framework data layer or a library such as TanStack Query, SWR, or RTK Query can add caching, refetching, and invalidation when the application needs them.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  44. Explain the composition pattern in React

    The composition pattern in React is the practice of building UIs by combining smaller, reusable components instead of extending them through inheritance. The most common forms are: passing children (props.children), passing components as named props (slots), specialization (a more specific component that wraps a generic one and fixes some props), render props / "children as a function", and compound components (a parent component that exposes a set of related sub-components, e.g. <Tabs> with <Tabs.List> and <Tabs.Panel>). Composition is React's main reuse mechanism, alongside custom hooks for behavior.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  45. What is virtual DOM in React?

    The "virtual DOM" in React is a tree of plain JavaScript objects (React elements) that describes what the UI should look like — it is not a copy of the actual DOM. When state or props change, React builds a new tree, compares it with the previous one (a process called reconciliation, performed by the Fiber reconciler since React 16), and applies only the necessary changes to the real DOM. The React team now prefers the terms "React elements" and "Fiber tree." The main benefit is the declarative programming model, not raw speed over hand-written DOM updates.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  46. How does virtual DOM in React work? What are its benefits and downsides?

    The "virtual DOM" is not a copy of the browser DOM. It is shorthand for the React element descriptions produced by components, together with React's internal Fiber tree. During rendering, React reconciles a new description with the previous one; during commit, it applies the required host-environment changes. This model enables declarative UI, batching, interruption, and multiple renderers, but diffing and retaining an extra tree have costs. It is a predictable update strategy, not a guarantee that React beats carefully written direct DOM code.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  47. What is React Fiber and how is it an improvement over the previous approach?

    Fiber is React's internal reconciliation architecture, introduced in React 16. A Fiber represents a unit of work and links to related Fibers in the component tree. This structure lets React assign priorities, pause or abandon interruptible renders, and commit completed work separately. It is the foundation for concurrent features such as transitions and Suspense, but it does not make every update asynchronous or guarantee that expensive rendering will be fast.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  48. What is reconciliation in React?

    Reconciliation is React's render-phase process for matching a newly returned element tree with the previous tree. Element types, positions, and keys determine whether React preserves a component and its state or replaces it. Reconciliation calculates the required changes; the separate commit phase applies those changes to the DOM. A render can therefore occur without any DOM mutation.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  49. What is React Suspense and what does it enable?

    Suspense lets React display a fallback while a descendant is not ready to render. Supported sources include code loaded with lazy, cached promises read with React 19's use API, React Server Components, and Suspense-enabled framework or library integrations. Suspense coordinates pending UI; an error boundary is still needed for rejected promises, and arbitrary asynchronous work does not activate Suspense automatically.

    const LazyComponent = React.lazy(() => import('./LazyComponent'));
    
    function MyComponent() {
      return (
        <React.Suspense fallback={<div>Loading...</div>}>
          <LazyComponent />
        </React.Suspense>
      );
    }

    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

  50. Explain what happens when the useState setter function is called in React

    Calling a useState setter queues either a replacement value or an updater function for the component's next render. It does not change the state variable in the currently running code because each render sees a snapshot of state. React batches updates where possible, processes queued updaters in order, renders with the resulting state, and commits any required DOM changes. If the final state is Object.is-equal to the current state, React can skip rendering the children. useReducer dispatches follow the same scheduling model; the API is distinct from class-based this.setState.


    Read the detailed answer on GreatFrontEnd which allows progress tracking, contains more code samples, and useful resources.

    Back to top ↑

About

Most important React.js interview questions for busy Frontend Engineers (updated for 2026)

Topics

Resources

Stars

6.0k stars

Watchers

14 watching

Forks

Used by

Contributors

Languages