Performance and Advanced React Interview Questions

Table of Contents +

This section focuses on the more advanced side of React interviews. It covers rendering performance, error boundaries, lazy loading, Suspense, Strict Mode, concurrent rendering ideas, diffing, Fiber, and related optimization topics.

This page includes 69 questions in this topic group.

What is โ€œkeyโ€ prop and what is the benefit of using it in arrays of elements?

A key is a special attribute you should include when mapping over arrays to render data. Key prop helps React identify which items have changed, are added, or are removed.

Keys should be unique among its siblings. Most often we use ID from our data as key:

const todoItems = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);

When you donโ€™t have stable IDs for rendered items, you may use the item index as a key as a last resort:

const todoItems = todos.map((todo, index) => (
<li key={index}>{todo.text}</li>
));

Benefits of key:

  • Enables React to efficiently update and re-render components.
  • Prevents unnecessary re-renders by reusing components when possible.
  • Helps maintain internal state of list items correctly.

Note:

  1. Using indexes for keys is not recommended if the order of items may change. This can negatively impact performance and may cause issues with component state.
  2. If you extract list item as separate component then apply keys on list component instead of li tag.
  3. There will be a warning message in the console if the key prop is not present on list items.
  4. The key attribute accepts either string or number and internally convert it as string type.
  5. Donโ€™t generate the key on the fly something like key={Math.random()}. Because the keys will never match up between re-renders and DOM created everytime.

What is Virtual DOM?

The Virtual DOM (VDOM) is a lightweight, in-memory representation of Real DOM used by libraries like React to optimize UI rendering. The representation of a UI is kept in memory and synced with the โ€œrealโ€ DOM. Itโ€™s a step that happens between the render function being called and the displaying of elements on the screen. This entire process is called reconciliation.

How Virtual DOM works?

The Virtual DOM works in five simple steps.

1. Initial Render
When a UI component renders for the first time, it returns JSX. React uses this structure to create a Virtual DOM tree, which is a lightweight copy of the actual DOM. This Virtual DOM is then used to build and render the Real DOM in the browser.

2. State or Props Change
When the componentโ€™s state or props change, React creates a new Virtual DOM reflecting the updated UI. However, it doesnโ€™t immediately update the Real DOM; instead, it works in memory to prepare for an efficient update.

3. Diffing Algorithm
React then compares the new Virtual DOM with the previous one using a process called diffing. It determines what has changed between the two versions and identifies the minimal set of updates needed.

4. Reconciliation
Based on the diffing results, React decides which parts of the Real DOM should be updated. It avoids re-rendering the entire DOM and instead updates only the elements that actually changed.

5. Efficient DOM Updates
This entire process-working with the Virtual DOM, diffing, and selective updating-makes the UI rendering much faster and more efficient than manipulating the Real DOM directly.

What is the difference between Shadow DOM and Virtual DOM?

The Shadow DOM is a browser technology designed primarily for scoping variables and CSS in web components. The Virtual DOM is a concept implemented by libraries in JavaScript on top of browser APIs.

The key differences in a table format shown below:

FeatureShadow DOMVirtual DOM
PurposeEncapsulation for Web ComponentsEfficient UI rendering
Managed byBrowserJS frameworks (e.g., React)
DOM TypePart of real DOM (scoped)In-memory representation
EncapsulationYesNo
Use CaseWeb Components, scoped stylingUI diffing and minimal DOM updates

What is React Fiber?

React Fiber is the new reconciliation engine in React, introduced in React 16. Itโ€™s a complete rewrite of Reactโ€™s core algorithm(old stack-based algorithm) for rendering and updating the UI. Fiber enhances Reactโ€™s ability to handle asynchronous rendering, prioritized updates(assign priority to different types of updates), and interruption(ability to pause, abort, or reuse work) of rendering work, enabling smoother and more responsive user interfaces.

What is the main goal of React Fiber?

The goal of React Fiber is to increase its suitability for areas like animation, layout, and gestures. Its headline feature is incremental rendering: the ability to split rendering work into chunks and spread it out over multiple frames.

Its main goals are:

  • Incremental Rendering โ€“ Breaks work into chunks for smoother updates.
  • Interruptible Rendering โ€“ Pauses and resumes rendering to keep the UI responsive.
  • Prioritization โ€“ Handles high-priority updates (e.g. animations) before low-priority ones.
  • Concurrency Support โ€“ Enables working on multiple UI versions simultaneously.
  • Better Error Handling โ€“ Supports component-level error boundaries.
  • Suspense Support โ€“ Allows waiting for async data before rendering.
  • Improved DevTools โ€“ Enables better debugging and performance tracking.

What is reconciliation?

Reconciliation is the process through which React updates the Browser DOM and makes React work faster. React use a diffing algorithm so that component updates are predictable and faster. React would first calculate the difference between the real DOM and the copy of DOM (Virtual DOM) when thereโ€™s an update of components. React stores a copy of Browser DOM which is called Virtual DOM. When we make changes or add data, React creates a new Virtual DOM and compares it with the previous one. This comparison is done by Diffing Algorithm. Now React compares the Virtual DOM with Real DOM. It finds out the changed nodes and updates only the changed nodes in Real DOM leaving the rest nodes as it is. This process is called Reconciliation.

Does the lazy function support named exports?

No, currently React.lazy function supports default exports only. If you would like to import modules which are named exports, you can create an intermediate module that reexports it as the default. It also ensures that tree shaking keeps working and donโ€™t pull unused components. Letโ€™s take a component file which exports multiple named components,

MoreComponents.js
export const SomeComponent = /* ... */;
export const UnusedComponent = /* ... */;

and reexport MoreComponents.js components in an intermediate file IntermediateComponent.js

IntermediateComponent.js
export { SomeComponent as default } from "./MoreComponents.js";

Now you can import the module using lazy function as below,

import React, { lazy } from "react";
const SomeComponent = lazy(() => import("./IntermediateComponent.js"));

How do you memoize a component?

There are memoize libraries available which can be used on function components.

For example moize library can memoize the component in another component.

import moize from "moize";
import Component from "./components/Component"; // this module exports a non-memoized component
const MemoizedFoo = moize.react(Component);
const Consumer = () => {
<div>
{"I will memoize the following entry:"}
<MemoizedFoo />
</div>;
};

Update: Since React v16.6.0, we have a React.memo. It provides a higher order component which memoizes component unless the props change. To use it, simply wrap the component using React.memo before you use it.

const MemoComponent = React.memo(function MemoComponent(props) {
/* render using props */
});
OR;
export default React.memo(MyFunctionComponent);

How you implement Server Side Rendering or SSR?

React is already equipped to handle rendering on Node servers. A special version of the DOM renderer is available, which follows the same pattern as on the client side.

import ReactDOMServer from "react-dom/server";
import App from "./App";
ReactDOMServer.renderToString(<App />);

This method will output the regular HTML as a string, which can be then placed inside a page body as part of the server response. On the client side, React detects the pre-rendered content and seamlessly picks up where it left off.

How do you enable production mode in React?

You should use Webpackโ€™s DefinePlugin method to set NODE_ENV to production, by which it strip out things like propType validation and extra warnings. Apart from this, if you minify the code, for example, Uglifyโ€™s dead-code elimination to strip out development only code and comments, it will drastically reduce the size of your bundle.

What is React memo function?

Class components can be restricted from re-rendering when their input props are the same using PureComponent or shouldComponentUpdate. Now you can do the same with function components by wrapping them in React.memo.

const MyComponent = React.memo(function MyComponent(props) {
/* only rerenders if props change */
});

What is React lazy function?

The React.lazy function lets you render a dynamic import as a regular component. It will automatically load the bundle containing the OtherComponent when the component gets rendered. This must return a Promise which resolves to a module with a default export containing a React component.

const OtherComponent = React.lazy(() => import("./OtherComponent"));
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}

Note: React.lazy and Suspense is not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we still recommend React Loadable.

How do you prevent unnecessary updates using setState?

You can compare the current value of the state with an existing state value and decide whether to rerender the page or not. If the values are the same then you need to return null to stop re-rendering otherwise return the latest state value.

For example, the user profile information is conditionally rendered as follows,

getUserProfile = (user) => {
const latestAddress = user.address;
this.setState((state) => {
if (state.address === latestAddress) {
return null;
} else {
return { title: latestAddress };
}
});
};

How do you render Array, Strings and Numbers in React 16 Version?

Arrays: Unlike older releases, you donโ€™t need to make sure render method return a single element in React16. You are able to return multiple sibling elements without a wrapping element by returning an array.

For example, letโ€™s take the below list of developers,

const ReactJSDevs = () => {
return [
<li key="1">John</li>,
<li key="2">Jackie</li>,
<li key="3">Jordan</li>,
];
};

You can also merge this array of items in another array component.

const JSDevs = () => {
return (
<ul>
<li>Brad</li>
<li>Brodge</li>
<ReactJSDevs />
<li>Brandon</li>
</ul>
);
};

Strings and Numbers: You can also return string and number type from the render method.

render() {
return 'Welcome to ReactJS questions';
}
// Number
render() {
return 2018;
}

Can you describe about componentDidCatch lifecycle method signature?

The componentDidCatch lifecycle method is invoked after an error has been thrown by a descendant component. The method receives two parameters,

  1. error: - The error object which was thrown
  2. info: - An object with a componentStack key contains the information about which component threw the error.

The method structure would be as follows

componentDidCatch(error, info);

In which scenarios do error boundaries not catch errors?

Here are the cases in which error boundaries donโ€™t work,

  1. Inside Event handlers
  2. Asynchronous code using setTimeout or requestAnimationFrame callbacks
  3. During Server side rendering
  4. When errors thrown in the error boundary code itself

What is the behavior of uncaught errors in react 16?

In React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree. The reason behind this decision is that it is worse to leave corrupted UI in place than to completely remove it. For example, it is worse for a payments app to display a wrong amount than to render nothing.

What is the proper placement for error boundaries?

The granularity of error boundaries usage is up to the developer based on project needs. You can follow either of these approaches,

  1. You can wrap top-level route components to display a generic error message for the entire application.
  2. You can also wrap individual components in an error boundary to protect them from crashing the rest of the application.

What is the benefit of component stack trace from error boundary?

Apart from error messages and javascript stack, React16 will display the component stack trace with file names and line numbers using error boundary concept.

For example, BuggyCounter component displays the component stack trace as below,

What are default props?

The defaultProps can be defined as a property on the component to set the default values for the props. These default props are used when props not supplied(i.e., undefined props), but not for null or 0 as props. That means, If you provide null value then it remains null value. Itโ€™s the same behavior with 0 as well.

For example, letโ€™s create color default prop for the button component,

function MyButton {
// ...
}
MyButton.defaultProps = {
color: "red",
};

If props.color is not provided then it will set the default value to โ€˜redโ€™. i.e, Whenever you try to access the color prop it uses the default value

function MyButton() {
return <MyButton />; // props.color will contain red value
}

What is the purpose of displayName class property?

The displayName string is used in debugging messages. Usually, you donโ€™t need to set it explicitly because itโ€™s inferred from the name of the function or class that defines the component. You might want to set it explicitly if you want to display a different name for debugging purposes or when you create a higher-order component.

For example, To ease debugging, choose a display name that communicates that itโ€™s the result of a withSubscription HOC.

function withSubscription(WrappedComponent) {
class WithSubscription extends React.Component {
/* ... */
}
WithSubscription.displayName = `WithSubscription(${getDisplayName(
WrappedComponent
)})`;
return WithSubscription;
}
function getDisplayName(WrappedComponent) {
return (
WrappedComponent.displayName || WrappedComponent.name || "Component"
);
}

What is the browser support for react applications?

React supports all popular browsers, including Internet Explorer 9 and above, although some polyfills are required for older browsers such as IE 9 and IE 10. If you use es5-shim and es5-sham polyfill then it even support old browsers that doesnโ€™t support ES5 methods.

What is code-splitting?

Code-Splitting is a feature supported by bundlers like Webpack and Browserify which can create multiple bundles that can be dynamically loaded at runtime. The react project supports code splitting via dynamic import() feature.

For example, in the below code snippets, it will make moduleA.js and all its unique dependencies as a separate chunk that only loads after the user clicks the โ€˜Loadโ€™ button.

moduleA.js

const moduleA = "Hello";
export { moduleA };

App.js

export default function App {
function handleClick() {
import("./moduleA")
.then(({ moduleA }) => {
// Use moduleA
})
.catch((err) => {
// Handle failure
});
};
return (
<div>
<button onClick={this.handleClick}>Load</button>
</div>
);
}

Class-based version

import React, { Component } from "react";
class App extends Component {
handleClick = () => {
import("./moduleA")
.then(({ moduleA }) => {
// Use moduleA
})
.catch((err) => {
// Handle failure
});
};
render() {
return (
<div>
<button onClick={this.handleClick}>Load</button>
</div>
);
}
}
export default App;

What are Keyed Fragments?

The Fragments declared with the explicit <React.Fragment> syntax may have keys. The general use case is mapping a collection to an array of fragments as below,

function Glossary(props) {
return (
<dl>
{props.items.map((item) => (
// Without the `key`, React will fire a key warning
<React.Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</React.Fragment>
))}
</dl>
);
}

Note: key is the only attribute that can be passed to Fragment. In the future, there might be a support for additional attributes, such as event handlers.

Does React support all HTML attributes?

As of React 16, both standard or custom DOM attributes are fully supported. Since React components often take both custom and DOM-related props, React uses the camelCase convention just like the DOM APIs.

letโ€™s take few props with respect to standard HTML attributes,

<div tabIndex="-1" /> // Just like node.tabIndex DOM API
<div className="Button" /> // Just like node.className DOM API
<input readOnly={true} /> // Just like node.readOnly DOM API

These props work similarly to the corresponding HTML attributes, with the exception of the special cases. It also support all SVG attributes.

When component props defaults to true?

If you pass no value for a prop, it defaults to true. This behavior is available so that it matches the behavior of HTML.

For example, below expressions are equivalent,

<MyInput autocomplete />
<MyInput autocomplete={true} />

Note: It is not recommended to use this approach because it can be confused with the ES6 object shorthand (example, {name} which is short for {name: name})

How JSX prevents Injection Attacks?

React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything thatโ€™s not explicitly written in your application. Everything is converted to a string before being rendered.

For example, you can embed user input as below,

const name = response.potentiallyMaliciousInput;
const element = <h1>{name}</h1>;

This way you can prevent XSS(Cross-site-scripting) attacks in the application.

How do you update rendered elements?

You can update UI(represented by rendered element) by passing the newly created element to ReactDOMโ€™s render method.

For example, lets take a ticking clock example, where it updates the time by calling render method multiple times,

function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById("root"));
}
setInterval(tick, 1000);

How do you say that props are readonly?

When you declare a component as a function or a class, it must never modify its own props.

letโ€™s take a below capital function,

function capital(amount, interest) {
return amount + interest;
}

The above function is called โ€œpureโ€ because it does not attempt to change their inputs, and always return the same result for the same inputs. Hence, React has a single rule saying โ€œAll React components must act like pure functions with respect to their props.โ€

What are the conditions to safely use the index as a key?

There are three conditions to make sure, it is safe use the index as a key.

  1. The list and items are staticโ€“ they are not computed and do not change
  2. The items in the list have no ids
  3. The list is never reordered or filtered.

Should keys be globally unique?

The keys used within arrays should be unique among their siblings but they donโ€™t need to be globally unique. i.e, You can use the same keys with two different arrays.

For example, the below Book component uses two arrays with different arrays,

function Book(props) {
const index = (
<ul>
{props.pages.map((page) => (
<li key={page.id}>{page.title}</li>
))}
</ul>
);
const content = props.pages.map((page) => (
<div key={page.id}>
<h3>{page.title}</h3>
<p>{page.content}</p>
<p>{page.pageNumber}</p>
</div>
));
return (
<div>
{index}
<hr />
{content}
</div>
);
}

Formik is a form library for react which provides solutions such as validation, keeping track of the visited fields, and handling form submission.

In detail, You can categorize them as follows,

  1. Getting values in and out of form state
  2. Validation and error messages
  3. Handling form submission

It is used to create a scalable, performant, form helper with a minimal API to solve annoying stuff.

Why are you not required to use inheritance?

In React, it is recommended to use composition over inheritance to reuse code between components. Both Props and composition give you all the flexibility you need to customize a componentโ€™s look and behavior explicitly and safely. Whereas, If you want to reuse non-UI functionality between components, it is suggested to extract it into a separate JavaScript module. Later components import it and use that function, object, or class, without extending it.

Can you use web components in react application?

Yes, you can use web components in a react application. Even though many developers wonโ€™t use this combination, it may require especially if you are using third-party UI components that are written using Web Components.

For example, letโ€™s use Vaadin date picker web component as below,

import "./App.css";
import "@vaadin/vaadin-date-picker";
export default function App() {
return (
<div className="App">
<vaadin-date-picker label="When were you born?"></vaadin-date-picker>
</div>
);
}

What is dynamic import?

You can achieve code-splitting in your app using dynamic import.

Letโ€™s take an example of addition,

  1. Normal Import
import { add } from "./math";
console.log(add(10, 20));
  1. Dynamic Import
import("./math").then((math) => {
console.log(math.add(10, 20));
});

What are loadable components?

With the release of React 18, React.lazy and Suspense are now available for server-side rendering. However, prior to React 18, it was recommended to use Loadable Components for code-splitting in a server-side rendered app because React.lazy and Suspense were not available for server-side rendering. Loadable Components lets you render a dynamic import as a regular component. For example, you can use Loadable Components to load the OtherComponent in a separate bundle like this:

import loadable from "@loadable/component";
const OtherComponent = loadable(() => import("./OtherComponent"));
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}

Now OtherComponent will be loaded in a separated bundle Loadable Components provides additional benefits beyond just code-splitting, such as automatic code reloading, error handling, and preloading. By using Loadable Components, you can ensure that your application loads quickly and efficiently, providing a better user experience for your users.

What is suspense component?

React Suspense is a built-in feature that lets you defer rendering part of your component tree until some condition(asynchronous operation) is met-usually, data or code has finished loading. While waiting, Suspense lets you display a fallback UI like a spinner or placeholder.

  1. Lazy loading components uses suspense feature,

    If the module containing the dynamic import is not yet loaded by the time parent component renders, you must show some fallback content while youโ€™re waiting for it to load using a loading indicator. This can be done using Suspense component.

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

    The above component shows fallback UI instead real component until OtherComponent is fully loaded.

  2. As an another example, suspend until async data(data fetching) is ready

function UserProfile() {
const user = use(fetchUser()); // throws a promise internally
return <div>{user.name}</div>;
}
function App() {
return (
<Suspense fallback={<div>Loading user...</div>}>
<UserProfile />
</Suspense>
);
}

What is route based code splitting?

One of the best place to do code splitting is with routes. The entire page is going to re-render at once so users are unlikely to interact with other elements in the page at the same time. Due to this, the user experience wonโ€™t be disturbed.

letโ€™s take an example of route based website using libraries like React Router with React.lazy,

import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import React, { Suspense, lazy } from "react";
const Home = lazy(() => import("./routes/Home"));
const About = lazy(() => import("./routes/About"));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Suspense>
</Router>
);

In the above code, the code splitting will happen at each route level.

What is diffing algorithm?

React needs to use algorithms to find out how to efficiently update the UI to match the most recent tree. The diffing algorithms is generating the minimum number of operations to transform one tree into another. However, the algorithms have a complexity in the order of O(nยณ) where n is the number of elements in the tree.

In this case, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:

  1. Two elements of different types will produce different trees.
  2. The developer can hint at which child elements may be stable across different renders with a key prop.

What are the rules covered by diffing algorithm?

When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements. It covers the below rules during reconciliation algorithm,

  1. Elements Of Different Types: Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. For example, elements <a> to <img>, or from <Article> to <Comment> of different types lead a full rebuild.

  2. DOM Elements Of The Same Type: When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes. Letโ€™s take an example with same DOM elements except className attribute,

    <div className="show" title="ReactJS" />
    <div className="hide" title="ReactJS" />
  3. Component Elements Of The Same Type: When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls componentWillReceiveProps() and componentWillUpdate() on the underlying instance. After that, the render() method is called and the diff algorithm recurses on the previous result and the new result.

  4. Recursing On Children: when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever thereโ€™s a difference. For example, when adding an element at the end of the children, converting between these two trees works well.

    <ul>
    <li>first</li>
    <li>second</li>
    </ul>
    <ul>
    <li>first</li>
    <li>second</li>
    <li>third</li>
    </ul>
  5. Handling keys: React supports a key attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree. For example, adding a key can make the tree conversion efficient,

<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>

When do you need to use refs?

There are few use cases to go for refs,

  1. Managing focus, text selection, or media playback.
  2. Triggering imperative animations.
  3. Integrating with third-party DOM libraries.

Must prop be named as render for render props?

Even though the pattern named render props, you donโ€™t have to use a prop named render to use this pattern. i.e, Any prop that is a function that a component uses to know what to render is technically a โ€œrender propโ€. Letโ€™s take an example with the children prop for render props,

<Mouse
children={(mouse) => (
<p>
The mouse position is {mouse.x}, {mouse.y}
</p>
)}
/>

Actually children prop doesnโ€™t need to be named in the list of โ€œattributesโ€ in JSX element. Instead, you can keep it directly inside element,

<Mouse>
{(mouse) => (
<p>
The mouse position is {mouse.x}, {mouse.y}
</p>
)}
</Mouse>

While using this above technique(without any name), explicitly state that children should be a function in your propTypes.

Mouse.propTypes = {
children: PropTypes.func.isRequired,
};

What are the problems of using render props with pure components?

If you create a function inside a render method, it negates the purpose of pure component. Because the shallow prop comparison will always return false for new props, and each render in this case will generate a new value for the render prop. You can solve this issue by defining the render function as instance method.

What is windowing technique?

Windowing is a technique that only renders a small subset of your rows at any given time, and can dramatically reduce the time it takes to re-render the components as well as the number of DOM nodes created. If your application renders long lists of data then this technique is recommended. Both react-window and react-virtualized are popular windowing libraries which provides several reusable components for displaying lists, grids, and tabular data.

How do you print falsy values in JSX?

The falsy values such as false, null, undefined, and true are valid children but they donโ€™t render anything. If you still want to display them then you need to convert it to string. Letโ€™s take an example on how to convert to a string,

<div>My JavaScript variable is {String(myVariable)}.</div>

What is the typical use case of portals?

React Portals are primarily used to render UI components such as modals, tooltips, dropdowns, hovercards, and notifications outside of their parent componentโ€™s DOM tree. This helps avoid common CSS issues caused by parent elements, such as:

  • **overflow: hidden** on parent elements clipping or hiding child elements like modals or tooltips,
  • stacking context and **z-index** conflicts created by parent containers that prevent child elements from appearing above other content.

That means, you need to visually โ€œbreak outโ€ of its container. By rendering these UI elements into a separate DOM node (often directly under <body>), portals ensure they appear above all other content and are not restricted by the parentโ€™s CSS or layout constraints, resulting in correct positioning and visibility regardless of the parentโ€™s styling.

What is the difference between Real DOM and Virtual DOM?

Here are the main differences between Real DOM and Virtual DOM,

Real DOMVirtual DOM
Updates are slowUpdates are fast
DOM manipulation is very expensive.DOM manipulation is very easy
You can update HTML directly.You Canโ€™t directly update HTML
It causes too much of memory wastageThere is no memory wastage
Creates a new DOM if element updatesIt updates the JSX if element update

What is Concurrent Rendering?

The Concurrent rendering makes React apps to be more responsive by rendering component trees without blocking the main UI thread. It allows React to interrupt a long-running render to handle a high-priority event. i.e, When you enabled concurrent Mode, React will keep an eye on other tasks that need to be done, and if thereโ€™s something with a higher priority it will pause what it is currently rendering and let the other task finish first. You can enable this in two ways,

// 1. Part of an app by wrapping with ConcurrentMode
<React.unstable_ConcurrentMode>
<Something />
</React.unstable_ConcurrentMode>;
// 2. Whole app using createRoot
ReactDOM.unstable_createRoot(domNode).render(<App />);

What is the difference between async mode and concurrent mode?

Both refers the same thing. Previously concurrent Mode being referred to as โ€œAsync Modeโ€ by React team. The name has been changed to highlight Reactโ€™s ability to perform work on different priority levels. So it avoids the confusion from other approaches to Async Rendering.

Can you use javascript urls in react16.9?

Yes, you can use javascript: URLs but it will log a warning in the console. Because URLs starting with javascript: are dangerous by including unsanitized output in a tag like <a href> and create a security hole.

const companyProfile = {
website: "javascript: alert('Your website is hacked')",
};
// It will log a warning
<a href={companyProfile.website}>More details</a>;

Remember that the future versions will throw an error for javascript URLs.

What are the benefits of new JSX transform?

There are three major benefits of new JSX transform,

  1. You can use JSX without importing React packages
  2. The compiled output might improve the bundle size in a small amount
  3. The future improvements provides the flexibility to reduce the number of concepts to learn React.

How is the new JSX transform different from old transform?

The new JSX transform doesnโ€™t require React to be in scope. i.e, You donโ€™t need to import React package for simple scenarios.

Letโ€™s take an example to look at the main differences between the old and the new transform,

Old Transform:

import React from "react";
function App() {
return <h1>Good morning!!</h1>;
}

Now JSX transform convert the above code into regular JavaScript as below,

import React from "react";
function App() {
return React.createElement("h1", null, "Good morning!!");
}

New Transform:

The new JSX transform doesnโ€™t require any React imports

function App() {
return <h1>Good morning!!</h1>;
}

Under the hood JSX transform compiles to below code

import { jsx as _jsx } from "react/jsx-runtime";
function App() {
return _jsx("h1", { children: "Good morning!!" });
}

Note: You still need to import React to use Hooks.

What are React Server components?

React Server Component is a way to write React component that gets rendered in the server-side with the purpose of improving React app performance. These components allow us to load components from the backend.

Note: React Server Components is still under development and not recommended for production yet.

What is a wrapper component?

A wrapper in React is a component that wraps or surrounds another component or group of components. It can be used for a variety of purposes such as adding additional functionality, styling, or layout to the wrapped components.

For example, consider a simple component that displays a message:

const Message = ({ text }) => {
return <p>{text}</p>;
};

We can create a wrapper component that will add a border to the message component:

const MessageWrapper = (props) => {
return (
<div style={{ border: "1px solid black" }}>
<Message {...props} />
</div>
);
};

Now we can use the MessageWrapper component instead of the Message component and the message will be displayed with a border:

<MessageWrapper text="Hello World" />

Wrapper component can also accept its own props and pass them down to the wrapped component, for example, we can create a wrapper component that will add a title to the message component:

const MessageWrapperWithTitle = ({ title, ...props }) => {
return (
<div>
<h3>{title}</h3>
<Message {...props} />
</div>
);
};

Now we can use the MessageWrapperWithTitle component and pass title props:

<MessageWrapperWithTitle title="My Message" text="Hello World" />

This way, the wrapper component can add additional functionality, styling, or layout to the wrapped component while keeping the wrapped component simple and reusable.

What are the differences between Functional and Class Components?

There are two different ways to create components in ReactJS. The main differences are listed down as below,

1. Syntax:

The class components uses ES6 classes to create the components. It uses render function to display the HTML content in the webpage.

The syntax for class component looks like as below.

class App extends React.Component {
render() {
return <h1>This is a class component</h1>;
}
}

Note: The Pascal Case is the recommended approach to provide naming to a component.

Functional component has been improved over the years with some added features like Hooks. Here is a syntax for functional component.

function App() {
return (
<div className="App">
<h1>Hello, I'm a function component</h1>
</div>
);
}

2. State:

State contains information or data about a component which may change over time.

In class component, you can update the state when a user interacts with it or server updates the data using the setState() method. The initial state is going to be assigned in the Constructor() method using the this.state object and it is possible to assign different data types such as string, boolean, numbers, etc.

A simple example showing how we use the setState() and constructor():

class App extends Component {
constructor() {
super();
this.state = {
message: "This is a class component",
};
}
updateMessage() {
this.setState({
message: "Updating the class component",
});
}
render() {
return (
<>
<h1>{this.state.message}</h1>
<button
onClick={() => {
this.updateMessage();
}}>
Click!!
</button>
</>
);
}
}

You didnโ€™t use state in functional components because it was only supported in class components. But over the years hooks have been implemented in functional components which enables to use state too.

The useState() hook can used to implement state in functional components. It returns an array with two items: the first item is current state and the next one is a function (setState) that updates the value of the current state.

Letโ€™s see an example to demonstrate the state in functional components,

function App() {
const [message, setMessage] = useState("This is a functional component");
const updateMessage = () => {
setMessage("Updating the functional component");
};
return (
<div className="App">
<h1>{message} </h1>
<button onClick={updateMessage}>Click me!!</button>
</div>
);
}

3. Props:

Props are referred to as โ€œpropertiesโ€. The props are passed into React component just like arguments passed to a function. In other words, they are similar to HTML attributes.

The props are accessible in child class component using this.props as shown in below example,

class Child extends React.Component {
render() {
return (
<h1>
{" "}
This is a functional component and component name is {
this.props.name
}{" "}
</h1>
);
}
}
class Parent extends React.Component {
render() {
return (
<div className="Parent">
<Child name="First child component" />
<Child name="Second child component" />
</div>
);
}
}

Props in functional components are similar to that of the class components but the difference is the absence of โ€˜thisโ€™ keyword.

function Child(props) {
return (
<h1>
This is a child component and the component name is{props.name}
</h1>
);
}
function Parent() {
return (
<div className="Parent">
<Child name="First child component" />
<Child name="Second child component" />
</div>
);
}

What is strict mode in React?

React.StrictMode is a useful component for highlighting potential problems in an application. Just like <Fragment>, <StrictMode> does not render any extra DOM elements. It activates additional checks and warnings for its descendants. These checks apply for development mode only.

import { StrictMode } from "react";
function App() {
return (
<div>
<Header />
<StrictMode>
<div>
<ComponentOne />
<ComponentTwo />
</div>
</StrictMode>
<Header />
</div>
);
}

In the example above, the strict mode checks apply to <ComponentOne> and <ComponentTwo> components only. i.e., Part of the application only.

Note: Frameworks such as NextJS has this flag enabled by default.

What is the benefit of strict mode?

The <StrictMode> component will be helpful in the below cases,

  1. To find the bugs caused by impure rendering where the components will re-render twice.
  2. To find the bugs caused by missing cleanup of effects where the components will re-run effects one more extra time.
  3. Identifying components with unsafe lifecycle methods.
  4. Warning about legacy string ref API usage.
  5. Detecting unexpected side effects.
  6. Detecting legacy context API.
  7. Warning about deprecated findDOMNode usage

Why does strict mode render twice in React?

StrictMode renders components twice in development mode(not production) in order to detect any problems with your code and warn you about those problems. This is used to detect accidental side effects in the render phase. If you used create-react-app development tool then it automatically enables StrictMode by default.

const root = createRoot(document.getElementById("root"));
root.render(
<StrictMode>
<App />
</StrictMode>
);

If you want to disable this behavior then you can simply remove strict mode.

const root = createRoot(document.getElementById("root"));
root.render(<App />);

To detect side effects the following functions are invoked twice:

  1. Function component bodies, excluding the code inside event handlers.
  2. Functions passed to useState, useMemo, or useReducer (any other Hook)
  3. Class componentโ€™s constructor, render, and shouldComponentUpdate methods
  4. Class component static getDerivedStateFromProps method
  5. State updater functions

What are the rules of JSX?

The following 3 rules needs to be followed while using JSX in a react application.

  1. Return a single root element: If you are returning multiple elements from a component, wrap them in a single parent element. Otherwise you will receive the below error in your browser console.

    html Adjacent JSX elements must be wrapped in an enclosing tag.

  2. All the tags needs to be closed: Unlike HTML, all tags needs to closed explicitly with in JSX. This rule applies for self-closing tags(like hr, br and img tags) as well.

  3. Use camelCase naming: It is suggested to use camelCase naming for attributes in JSX. For example, the common attributes of HTML elements such as class, tabindex will be used as className and tabIndex.
    Note: There is an exception for aria-* and data-* attributes which should be lower cased all the time.

What are capture phase events?

The onClickCapture React event is helpful to catch all the events of child elements irrespective of event propagation logic or even if the events propagation stopped. This is useful if you need to log every click events for analytics purpose.

For example, the below code triggers the click event of parent first followed by second level child eventhough leaf child button elements stops the propagation.

<div onClickCapture={() => alert("parent")}>
<div onClickCapture={() => alert("child")}>
<button onClick={(e) => e.stopPropagation()} />
<button onClick={(e) => e.stopPropagation()} />
</div>
</div>

The event propagation for the above code snippet happens in the following order:

  1. It travels downwards in the DOM tree by calling all onClickCapture event handlers.
  2. It executes onClick event handler on the target element.
  3. It travels upwards in the DOM tree by call all onClick event handlers above to it.

How does React updates screen in an application?

React updates UI in three steps,

  1. Triggering or initiating a render: The component is going to triggered for render in two ways.

    1. Initial render: When the app starts, you can trigger the initial render by calling creatRoot with the target DOM node followed by invoking componentโ€™s render method. For example, the following code snippet renders App component on root DOM node.
    import { createRoot } from "react-dom/client";
    const root = createRoot(document.getElementById("root"));
    root.render(<App />);
    1. Re-render when the state updated: When you update the component state using the state setter function, the componenโ€™t state automatically queues for a render.
  2. Rendering components: After triggering a render, React will call your components to display them on the screen. React will call the root component for initial render and call the function component whose state update triggered the render. This is a recursive process for all nested components of the target component.

  3. Commit changes to DOM: After calling components, React will modify the DOM for initial render using appendChild() DOM API and apply minimal necessary DOM updates for re-renders based on differences between rerenders.

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.

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.

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.

What will happen by defining nested function components?

Technically it is possible to write nested function components but it is not suggested to write nested function definitions. Because it leads to unexpected bugs and performance issues.

Can you 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

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.

How does React Fiber works? Explain in detail.

React Fiber is the core engine that enables advanced features like concurrent rendering, prioritization, and interruptibility in React. Hereโ€™s how it works:

1. Fiber Tree Structure

Each component in your app is represented by a Fiber node in a tree structure. A Fiber node contains:

  • Component type
  • Props & state
  • Pointers to parent, child, and sibling nodes
  • Effect tags to track changes (e.g., update, placement)
  • This forms the Fiber Tree, a data structure React uses instead of the traditional call stack.

2. Two Phases of Rendering

A. Render Phase (work-in-progress)

  • React builds a work-in-progress Fiber tree.
  • It walks through each component (begin phase), calculates what needs to change, and collects side effects (complete phase).
  • This phase is interruptible-React can pause it and resume later.

B. Commit Phase

  • React applies changes to the Real DOM.
  • Runs lifecycle methods (e.g., componentDidMount, useEffect).
  • This phase is non-interruptible but fast.

3. Work Units and Scheduling

  • React breaks rendering into units of work (small tasks).
  • These units are scheduled based on priority using the React Scheduler.
  • If time runs out (e.g., user starts typing), React can pause and yield control back to the browser.

4. Double Buffering with Two Trees

  • React maintains two trees:
  • Current Tree โ€“ whatโ€™s visible on the screen.
  • Work-In-Progress Tree โ€“ the next version being built in memory.
  • Only after the new tree is fully ready, React commits it, making it the new current tree.

5. Concurrency and Prioritization

  • React can prepare multiple versions of UI at once (e.g., during slow data loading).
  • Updates can be assigned priorities, so urgent updates (like clicks) are handled faster than background work.

Share & Connect