Skip to content

greatfrontend/top-reactjs-interview-questions

Repository files navigation

Top React.js Interview Questions (Updated for 2025)

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


Black Friday 2025 sale going on now, enjoy the largest discount of the year! Get 30% off GreatFrontEnd Premium → 💡


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 a JavaScript library created by Facebook for building user interfaces, primarily for single-page applications. It allows developers to create reusable components that manage their own state. Key benefits of React include a component-based architecture for modular code, the virtual DOM for efficient updates, a declarative UI for more readable code, one-way data binding for predictable data flow, and a strong community and ecosystem with abundant resources and tools.

    Key characteristics of React:

    • Declarative: You describe the desired state of your UI based on data, and React handles updating the actual DOM efficiently.
    • Component-based: Build reusable and modular UI elements (components) that manage their own state and logic.
    • Virtual DOM: React uses a lightweight in-memory representation of the actual DOM, allowing it to perform updates selectively and efficiently.
    • JSX: While not mandatory, JSX provides a syntax extension that allows you to write HTML-like structures within your JavaScript code, making UI development more intuitive.

    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 anything React can render: a React Element, a string, a number, an array of nodes, a fragment, a portal, null, undefined, false, or true. A React Element is the immutable plain object React produces from JSX or React.createElement describing what to render. A React Component is a function (or, historically, a class) that accepts props and returns React Nodes. Elements describe the UI; components are the factories that produce those elements.


    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 stands for JavaScript XML. It is a syntax extension for JavaScript that allows you to write HTML-like code within JavaScript. JSX makes it easier to create React components by allowing you to write what looks like HTML directly in your JavaScript code. Under the hood, JSX is transformed into JavaScript function calls, typically using a tool like Babel. For example, <div>Hello, world!</div> in JSX is transformed into React.createElement('div', null, 'Hello, world!').


    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 is not allowed to mutate. State changes trigger a re-render of the owning component (and its descendants); prop changes happen because the parent re-rendered with new values. 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/array as the provider value on every render (which forces every consumer to re-render), assuming React.memo will stop context-driven re-renders (it won't), and reaching for context as a general-purpose state manager. For frequently-changing or independent slices of state, split context into multiple providers, memoize the value, or use a dedicated state library like Redux, Zustand, or Jotai.


    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 you use state and other React features in plain functions, without classes. They were introduced to solve real pain points in the class-component era — "wrapper hell" from HOCs and render props, the awkwardness of this binding, and the difficulty of sharing stateful logic between components. Custom hooks make that logic genuinely reusable through composition. React 19 expands the set further with hooks like use, useActionState, useOptimistic, and useFormStatus for promises, forms, and optimistic UI.


    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. Always call hooks at the top level of your component or custom hook — never inside loops, conditions, nested functions, or after an early return. Only call hooks from React function components or other custom hooks (whose names must start with use). Lean on eslint-plugin-react-hooks to enforce these rules. The React Compiler (RC/stable by 2026) relaxes the need for some manual memoization, but the rules of hooks themselves still apply.


    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 asynchronously after the browser has painted. It does not block the user from seeing the new frame. Use it for data fetching, subscriptions, logging, and most side effects.
    • 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, both fire twice on mount in Strict Mode development builds, and useLayoutEffect has no effect during server rendering (React warns if you use it in SSR).

    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.

    // Modern hooks form (preferred)
    const [count, setCount] = useState(0);
    
    const handleClick = () => {
      setCount((c) => c + 1);
      setCount((c) => c + 1); // Both run; final count is +2.
    };
    // Legacy class form
    this.setState((prevState, props) => ({
      counter: prevState.counter + props.increment,
    }));

    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 determines when the effect should re-run. If the array is empty, the effect runs only once after the initial render. If it contains variables, the effect runs whenever any of those variables change. If omitted, the effect runs after every render.


    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 React, { useRef, useEffect } 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 returns a memoized function whose identity only changes when one of its dependencies changes. The point is referential stability — so a React.memo-wrapped child does not re-render, or a useEffect whose deps include the function does not re-fire. Re-creating a plain function literal each render is essentially free; the actual cost being avoided is the downstream work triggered by a new reference.

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

    Note for 2026: with the React Compiler (stable in React 19), most components no longer need manual useCallback / useMemo / React.memo — the compiler memoizes automatically. New code targeting a compiler-enabled project should generally not reach for useCallback unless profiling shows a specific need.


    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?

    The useMemo hook in React is used to memoize expensive calculations so that they are only recomputed when one of the dependencies has changed. This can improve performance by avoiding unnecessary recalculations. You should use useMemo when you have a computationally expensive function that doesn't need to run on every render.

    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?

    Re-rendering in React refers to the process where a component updates its output to the DOM in response to changes in state or props. When a component's state or props change, React triggers a re-render to ensure the UI reflects the latest data. This process involves calling the component's render method again to produce a new virtual DOM, which is then compared to the previous virtual DOM to determine the minimal set of changes needed to update the actual DOM.


    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 deprecated. Function components can now accept ref as a regular prop, so wrapping in forwardRef() is no longer required. 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 recommends against mutating state because several of its mechanisms depend on the previous and next state being different objects (reference inequality). When you mutate state in place, the reference does not change, which breaks Object.is bailouts in useState/useReducer, breaks React.memo and useMemo/useEffect dependency comparisons, and can cause tearing under concurrent rendering. It also defeats time-travel debugging in React DevTools. Always produce a new object/array (with the spread operator, array methods like map/filter/toSorted, or a library such as Immer) and pass it to the state setter.


    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 in React are components that catch JavaScript errors thrown during rendering, in lifecycle methods, and in constructors of their child component tree, then display a fallback UI instead of crashing the whole application. They are implemented as class components using static getDerivedStateFromError (to render a fallback) and optionally componentDidCatch (for logging). Since React 16, an uncaught error unmounts the entire React tree, which makes error boundaries effectively required for production apps. Error boundaries do not catch errors inside event handlers, asynchronous code, or server-side rendering. As of React 19, there is still no hooks-based API for error boundaries — most teams use the react-error-boundary library, or rely on the new root-level onUncaughtError, onCaughtError, and onRecoverableError options on createRoot/hydrateRoot.


    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?

    To test React applications, use Jest or Vitest as the test runner together with React Testing Library, which encourages testing components the way users interact with them. Drive interactions with @testing-library/user-event (preferred over fireEvent), mock network calls with MSW, and write end-to-end tests with Playwright (or Cypress). For React 19 features like async components and Server Components, lean on async queries (findBy*, waitFor).


    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

    React hydration is the process of attaching event listeners and making a server-rendered HTML page interactive on the client side. When a React application is server-side rendered, the HTML is sent to the client, and React takes over to make it dynamic by attaching event handlers and initializing state. This process is called hydration.


    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?

    To debug React applications, use the React Developer Tools browser extension to inspect the component tree, props/state, and rendering with the Profiler. Enable Strict Mode during development to surface unsafe patterns, and rely on React 19.1 owner stacks for clearer component-aware stack traces. Use error boundaries (or the react-error-boundary package) to catch render-time errors, and reach for console.log, breakpoints, and the React DevTools "log" button for deeper inspection.


    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?

    React strict mode is a development tool that helps identify potential problems in an application. It activates additional checks and warnings for its descendants. It doesn't render any visible UI and doesn't affect the production build. The benefits include identifying unsafe lifecycle methods, warning about legacy string ref API usage, detecting unexpected side effects, and ensuring that components are resilient to future changes.


    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?

    The first thing to know in 2026 is that the React Compiler auto-memoizes components and values, so a lot of the manual useMemo/useCallback work that used to be required for context performance is now done for you — adopt it before reaching for other tricks. Beyond that, the canonical patterns are: split a single context into a state context and a dispatch (or setter) context so consumers that only dispatch don't rerender on state changes; memoize the value object you pass to the provider; wrap consumer components in React.memo; and reach for selector libraries like use-context-selector when you need to subscribe to a slice of a large value.

    const value = useMemo(() => ({ state }), [state]); // dispatch is already stable

    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 are largely a legacy pattern. The current React docs (React 19) discourage HOCs in favor of custom hooks for sharing logic between function components. You'll still see HOCs in older code and in libraries (e.g. connect from React Redux), but for new code, prefer hooks.


    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?

    The Flux pattern is an architectural design Facebook introduced for managing state in React applications. It enforces a unidirectional data flow, making it easier to manage and debug application state. Today Flux is largely historical — it has been superseded by libraries it inspired, such as Redux, Zustand, and the built-in useReducer + Context combination — but its single-source-of-truth and unidirectional-flow ideas are still the foundation of those tools.

    • 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.
      • Single source of truth for application 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 in a single direction: from parent components down to child components via props. Children cannot mutate the props they receive; to change parent state, a child invokes a callback the parent passed in. This contrasts with two-way binding (e.g. Angular or Vue's v-model), where view and model stay in sync automatically. The main benefits are predictable state changes, easier debugging, and patterns like controlled components, immutable updates, and time-travel debugging that fall out naturally from the constraint.


    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?

    In a modern React app, don't roll your own useEffect + fetch for data loading — the React docs explicitly recommend against it. Reach first for a dedicated data-fetching library: TanStack Query, SWR, or RTK Query for client-side fetching, or Server Components and route-level loaders (Next.js App Router, Remix/React Router) when you control the framework. In React 19, the new use() hook lets a component read a promise directly and suspend, which pairs naturally with <Suspense> for loading states and error boundaries for failures. A hand-written useEffect+fetch is a low-level fallback that needs an AbortController, a response.ok check, and careful state handling to avoid race conditions and stale updates.


    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) in React involves rendering React components on the server and sending the resulting HTML to the client. The browser displays that HTML immediately, then hydrateRoot attaches event handlers so the page becomes interactive. Modern React supports streaming SSR via renderToPipeableStream (Node) and renderToReadableStream (Web), and React Server Components let parts of the tree render only on the server. Benefits include faster perceived loads and better SEO; tradeoffs include a slower TTFB, the cost of hydration, and the risk of hydration mismatches.


    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) pre-renders pages to HTML at build time, instead of rendering them per request. The output is plain files that can be served from a CDN, which makes loads fast and SEO straightforward. Frameworks like Next.js, Remix, Astro, and Gatsby support it; in Next.js's App Router, fetches are statically generated by default and generateStaticParams enumerates dynamic routes at build. Incremental Static Regeneration (ISR) lets you re-build individual pages in the background after a TTL, so static does not have to mean stale. SSG is best for content that does not vary per user and does not need to be perfectly fresh.


    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 pitfalls when doing data fetching in React include not handling loading and error states, leaking requests by not aborting them on unmount, ignoring race conditions when props or query params change, fetching during render (which loops), and triggering request waterfalls. In modern React (18+), use AbortController for cleanup, account for StrictMode's intentional double-invoke in development, and prefer purpose-built libraries like TanStack Query, SWR, or RTK Query for caching and deduplication. React 19's use() hook plus Suspense, and Server Components, are now the recommended way to read promises in components.


    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 { useEffect, useState } from 'react';
    
    function DataFetcher({ url, children }) {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        fetch(url)
          .then((response) => response.json())
          .then(setData);
      }, [url]);
    
      return children(data);
    }
    
    // Usage
    <DataFetcher url="/api/data">
      {(data) => <div>{data ? data.name : 'Loading...'}</div>}
    </DataFetcher>;

    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. Use React Context to pass values that change rarely (theme, locale, current user) — Context is not a state manager and re-renders all consumers on every change. Reach for a client-state library like Zustand, Jotai, or Redux Toolkit when many unrelated components need to share frequently-changing state. Critically, treat server state separately: TanStack Query, SWR, or RTK Query handle caching, refetching, and invalidation far better than any general-purpose store.


    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 in React is a lightweight copy of the actual DOM. When the state of a component changes, React creates a new virtual DOM tree and compares it with the previous one using a process called "reconciliation." Only the differences are then updated in the actual DOM, making updates more efficient. The benefits include improved performance and a more declarative way to manage UI. However, it can add complexity and may not be as performant for very simple applications.


    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?

    React Fiber is a complete rewrite of React's reconciliation algorithm, introduced in React 16. It improves the rendering process by breaking down rendering work into smaller units, allowing React to pause and resume work, which makes the UI more responsive. This approach enables features like time slicing and suspense, which were not possible with the previous stack-based algorithm.


    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 in React is the process through which React updates the DOM to match the virtual DOM. When a component's state or props change, React creates a new virtual DOM tree and compares it with the previous one. This comparison process is called "diffing." React then updates only the parts of the actual DOM that have changed, making the updates efficient and fast.


    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?

    React Suspense is a feature that allows you to handle asynchronous operations in your React components more gracefully. It enables you to show fallback content while waiting for something to load, such as data fetching or code splitting. You can use it with React.lazy for code splitting and with libraries like react-query for data fetching.

    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

    When the setter function returned by the useState hook is called in React, it schedules an update to the component's state value. React then queues a re-render of the component with the new state. This process is typically asynchronous, and React batches multiple state updates together for performance.


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

    Back to top ↑

Contributors