FrontendDeveloper.in

React Interview Questions

  • Question 256

    How does React batch multiple state updates?

    React prevents component from re-rendering for each and every state update by grouping multiple state updates within an event handler. This strategy improves the application performance and this process known as batching. The older version of React only supported batching for browser events whereas React18 supported for asynchronous actions, timeouts and intervals along with native events. This improved version of batching is called automatic batching.

    Let's demonstrate this automatic batching feature with a below example.

    import { useState } from "react";
    
    export default function BatchingState() {
    const [count, setCount] = useState(0);
    const [message, setMessage] = useState("batching");
    
    console.log("Application Rendered");
    
    const handleAsyncFetch = () => {
    fetch("https://jsonplaceholder.typicode.com/users/1").then(() => {
    // Automatic Batching re-render only once
    setCount(count + 1);
    setMessage("users fetched");
    });
    };
    
    return (
    <>
    <h1>{count}</h1>
    <button onClick={handleAsyncFetch}>Click Me!</button>
    </>
    );
    }
    

    The preceding code updated two state variables with in an event handler. However, React will perform automatic batching feature and the component will be re-rendered only once for better performance.

  • Question 257

    Is it possible to prevent automatic batching?

    Yes, it is possible to prevent automatic batching default behavior. There might be cases where you need to re-render your component after each state update or updating one state depends on another state variable. Considering this situation, React introduced flushSync method from react-dom API for the usecases where you need to flush state updates to DOM immediately.

    The usage of flushSync method within an onClick event handler will be looking like as below,

    import { flushSync } from "react-dom";
    
    const handleClick = () => {
    flushSync(() => {
    setClicked(!clicked); //Component will create a re-render here
    });
    
    setCount(count + 1); // Component will create a re-render again here
    };
    

    In the above click handler, React will update DOM at first using flushSync and second time updates DOM because of the counter setter function by avoiding automatic batching.

  • Question 258

    What is React hydration?

    React hydration is used to add client-side JavaScript interactivity to pre-rendered static HTML generated by the server. It is used only for server-side rendering(SSR) to enhance the initial rendering time and make it SEO friendly application. This hydration acts as a bridge to reduce the gap between server side and client-side rendering.

    After the page loaded with generated static HTML, React will add application state and interactivity by attaching all event handlers for the respective elements. Let's demonstrate this with an example.

    Consider that React DOM API(using renderToString) generated HTML for <App> component which contains <button> element to increment the counter.

    import {useState} from 'react';
    import { renderToString } from 'react-dom/server';
    
    export default function App() {
    const [count, setCount] = React.useState(0);
    
    return (
    <h1>Counter</h1>
    <button onClick={() => setCount(prevCount => prevCount + 1)}>
    {count} times
    </button>
    );
    }
    
    const html = renderToString(<App />);
    

    The above code generates the below HTML with a header text and button component without any interactivity.

    <h1>Counter</h1>
    <button>
    <!-- -->0<!-- -->
    times
    </button>
    

    At this stage hydrateRoot API can be used to perform hydration by attaching onClick event handler.

    import { hydrateRoot } from "react-dom/client";
    import App from "./App.js";
    
    hydrateRoot(document.getElementById("root"), <App />);
    

    After this step, you are able to run React application on server-side and hydrating the javascript bundle on client-side for smooth user experience and SEO purposes.

  • Question 259

    How do you update objects inside state?

    You cannot update the objects which exists in the state directly. Instead, you should create a fresh new object (or copy from the existing object) and update the latest state using the newly created object. Eventhough JavaScript objects are mutable, you need to treat objects inside state as read-only while updating the state.

    Let's see this comparison with an example. The issue with regular object mutation approach can be described by updating the user details fields of Profile component. The properties of Profile component such as firstName, lastName and age details mutated in an event handler as shown below.

    import { useState } from "react";
    
    export default function Profile() {
    const [user, setUser] = useState({
    firstName: "John",
    lastName: "Abraham",
    age: 30,
    });
    
    function handleFirstNameChange(e) {
    user.firstName = e.target.value;
    }
    
    function handleLastNameChange(e) {
    user.lastName = e.target.value;
    }
    
    function handleAgeChange(e) {
    user.age = e.target.value;
    }
    
    return (
    <>
    <label>
    First name:
    <input value={user.firstName} onChange={handleFirstNameChange} />
    </label>
    <label>
    Last name:
    <input value={user.lastName} onChange={handleLastNameChange} />
    </label>
    <label>
    Age:
    <input value={user.age} onChange={handleAgeChange} />
    </label>
    Profile:
    {person.firstName} {person.lastName} ({person.age})
    </>
    );
    }
    

    Once you run the application with above user profile component, you can observe that user profile details won't be update upon entering the input fields. This issue can be fixed by creating a new copy of object which includes existing properties through spread syntax(...obj) and add changed values in a single event handler itself as shown below.

    handleProfileChange(e) {
    setUser({
    ...user,
    [e.target.name]: e.target.value
    });
    }
    

    The above event handler is concise instead of maintaining separate event handler for each field. Now, UI displays the updated field values as expected without an issue.

  • Question 260

    How do you update nested objects inside state?

    You cannot simply use spread syntax for all kinds of objects inside state. Because spread syntax is shallow and it copies properties for one level deep only. If the object has nested object structure, UI doesn't work as expected with regular JavaScript nested property mutation. Let's demonstrate this behavior with an example of User object which has address nested object inside of it.

    const user = {
    name: "John",
    age: 32,
    address: {
    country: "Singapore",
    postalCode: 440004,
    },
    };
    

    If you try to update the country nested field in a regular javascript fashion(as shown below) then user profile screen won't be updated with latest value.

    user.address.country = "Germany";
    

    This issue can be fixed by flattening all the fields into a top-level object or create a new object for each nested object and point it to it's parent object. In this example, first you need to create copy of address object and update it with the latest value. Later, the address object should be linked to parent user object something like below.

    setUser({
    ...user,
    address: {
    ...user.address,
    country: "Germany",
    },
    });
    

    This approach is bit verbose and not easy for deep hierarchical state updates. But this workaround can be used for few levels of nested objects without much hassle.

  • Question 261

    How do you update arrays inside state?

    Eventhough arrays in JavaScript are mutable in nature, you need to treat them as immutable while storing them in a state. That means, similar to objects, the arrays cannot be updated directly inside state. Instead, you need to create a copy of the existing array and then set the state to use newly copied array.

    To ensure that arrays are not mutated, the mutation operations like direct direct assignment(arr[1]='one'), push, pop, shift, unshift, splice etc methods should be avoided on original array. Instead, you can create a copy of existing array with help of array operations such as filter, map, slice, spread syntax etc.

    For example, the below push operation doesn't add the new todo to the total todo's list in an event handler.

    onClick = {
    todos.push({
    id: id+1,
    name: name
    })
    }
    

    This issue is fixed by replacing push operation with spread syntax where it will create a new array and the UI updated with new todo.

    onClick = {
    [
    ...todos,
    { id: id+1, name: name }
    ]
    }
    
  • Question 262

    How do you use immer library for state updates?

    Immer library enforces the immutability of state based on copy-on-write mechanism. It uses JavaScript proxy to keep track of updates to immutable states. Immer has 3 main states as below,

    1. Current state: It refers to actual state
    2. Draft state: All new changes will be applied to this state. In this state, draft is just a proxy of the current state.
    3. Next state: It is formed after all mutations applied to the draft state

    Immer can be used by following below instructions,

    1. Install the dependency using npm install use-immer command
    2. Replace useState hook with useImmer hook by importing at the top
    3. The setter function of useImmer hook can be used to update the state.

    For example, the mutation syntax of immer library simplifies the nested address object of user state as follows,

    import { useImmer } from "use-immer";
    const [user, setUser] = useImmer({
    name: "John",
    age: 32,
    address: {
    country: "Singapore",
    postalCode: 440004,
    },
    });
    
    //Update user details upon any event
    setUser((draft) => {
    draft.address.country = "Germany";
    });
    

    The preceding code enables you to update nested objects with a conceise mutation syntax.

  • Question 263

    What are the preferred and non-preferred array operations for updating the state?

    The below table represent preferred and non-preferred array operations for updating the component state.

    ActionPreferredNon-preferred
    Addingconcat, [...arr]push, unshift
    Removingfilter, slicepop, shift, splice
    Replacingmapsplice, arr[i] = someValue
    sortingcopying to new arrayreverse, sort

    If you use Immer library then you can able to use all array methods without any problem.

  • Question 265

    Can I use keys for non-list items?

    Keys are primarily used for rendering list items but they are not just for list items. You can also use them React to distinguish components. By default, React uses order of the components in

  • Question 266

    What are the guidelines to be followed for writing reducers?

    There are two guidelines to be taken care while writing reducers in your code.

    1. Reducers must be pure without mutating the state. That means, same input always returns the same output. These reducers run during rendering time similar to state updater functions. So these functions should not send any requests, schedule time outs and any other side effects.

    2. Each action should describe a single user interaction even though there are multiple changes applied to data. For example, if you "reset" registration form which has many user input fields managed by a reducer, it is suggested to send one "reset" action instead of creating separate action for each fields. The proper ordering of actions should reflect the user interactions in the browser and it helps a lot for debugging purpose.

  • Question 267

    How does ReactJS work behind the scenes?

    ReactJS is a powerful JavaScript library for building user interfaces. While it appears simple on the surface, React performs a lot of complex operations behind the scenes to efficiently update the UI. Here's an overview of how it works internally:

    1. Virtual DOM & Component Rendering

    React doesn't manipulate the real DOM directly. Instead, it uses a Virtual DOM — a lightweight JavaScript representation of the UI.

    When a component renders (e.g., <App />):

    • React executes the component function (e.g., App()).
    • Hooks like useState are registered and tracked in order.
    • React builds a Virtual DOM tree from the returned JSX.
    • This virtual DOM is a plain JS object that describes the desired UI.

    This process ensures fast and efficient rendering before React decides how to update the real DOM.

    2. React Fiber Architecture

    React’s core engine is called Fiber, introduced in React 16. Fiber is a reimplementation of the React reconciliation algorithm with the following capabilities:

    • Breaks rendering work into units of work (fiber nodes).
    • Enables interruptible rendering (important for responsiveness).
    • Supports priority scheduling and concurrent rendering.

    Each Fiber node represents a component and stores:

    • The component type (function/class).
    • Props, state, and effects.
    • Links to parent, child, and sibling fibers.

    3. Reconciliation (Diffing Algorithm)

    When state or props change:

    • React re-executes the component to produce a new virtual DOM.
    • It compares the new virtual DOM to the previous one using an efficient diffing algorithm.
    • React determines the minimal set of DOM changes required.

    This process is known as reconciliation.

    4. Commit Phase (Real DOM Updates)

    Once reconciliation is done:

    • React enters the commit phase.
    • It applies calculated changes to the real DOM.
    • It also runs side effects like useEffect or useLayoutEffect.

    This is the only time React interacts directly with the browser DOM.

    5. Hooks and State Management

    With Hooks (like useState, useEffect):

    • React keeps an internal list of hooks per component.
    • Hooks are identified by their order in the function.
    • When state updates occur, React re-renders the component and re-runs the hooks in the same order.

    6. React Scheduler

    React uses an internal Scheduler to control how updates are prioritized:

    • Urgent tasks like clicks and inputs are processed immediately.
    • Non-urgent tasks (like data fetching) can be delayed or paused.
    • This improves responsiveness and allows for time slicing in Concurrent Mode.
  • Question 268

    How is `useReducer` Different from `useState`?

    There are notable differences between useState and useReducer hooks.

    FeatureuseStateuseReducer
    State complexitySimple (one variable or flat object)Complex, multi-part or deeply nested
    Update styleDirect (e.g. setState(x))Through actions (e.g. dispatch({}))
    Update logicIn componentIn reducer function
    Reusability & testingLess reusableHighly reusable & testable
  • Question 269

    What is useContext? What are the steps to follow for useContext?

    The useContext hook is a built-in React Hook that lets you access the value of a context inside a functional component without needing to wrap it in a <Context.Consumer> component.

    It helps you avoid prop drilling (passing props through multiple levels) by allowing components to access shared data like themes, authentication status, or user preferences.

    The usage of useContext involves three main steps:

    Step 1 : Create the Context

    Use React.createContext() to create a context object.

    import React, { createContext } from 'react';
    
    const ThemeContext = createContext(); // default value optional
    

    You typically export this so other components can import it.

    Step 2: Provide the Context Value

    Wrap your component tree (or a part of it) with the Context.Provider and pass a value prop.

    function App() {
    return (
    <ThemeContext.Provider value="dark">
    <MyComponent />
    </ThemeContext.Provider>
    );
    }
    

    Now any component inside <ThemeContext.Provider> can access the context value.

    Step 3: Consume the Context with **useContext**

    In any functional component inside the Provider, use the useContext hook:

    import { useContext } from 'react';
    function MyComponent() {
    const theme = useContext(ThemeContext); // theme = "dark"
    return <p>Current Theme: {theme}</p>;
    }
    
  • Question 270

    What are the use cases of useContext hook?

    The useContext hook in React is used to share data across components without having to pass props manually through each level. Here are some common and effective use cases:

    1. Theme Customization useContext can be used to manage application-wide themes, such as light and dark modes, ensuring consistent styling and enabling user-driven customization.
    2. Localization and Internationalization It supports localization by providing translated strings or locale-specific content to components, adapting the application for users in different regions.
    3. User Authentication and Session Management useContext allows global access to authentication status and user data. This enables conditional rendering of components and helps manage protected routes or user-specific UI elements.
    4. Shared Modal or Sidebar Visibility It's ideal for managing the visibility of shared UI components like modals, drawers, or sidebars, especially when their state needs to be controlled from various parts of the app.
    5. Combining with **useReducer** for Global State Management When combined with useReducer, useContext becomes a powerful tool for managing more complex global state logic. This pattern helps maintain cleaner, scalable state logic without introducing external libraries like Redux. Some of the common use cases of useContext are listed below,
Get LinkedIn Premium at Rs 399