Skip to the content.

React Basics

Click ★ if you like the project. Your contributions are heartily ♡ welcome.



Table of Contents


# 1. INTRODUCTION


Q. What is React.js?

React is a JavaScript library created for building fast and interactive user interfaces for web and mobile applications. It is an open-source, component-based, front-end library responsible only for the application view layer.

The main objective of ReactJS is to develop User Interfaces (UI) that improves the speed of the apps. It uses virtual DOM (JavaScript object), which improves the performance of the app. The JavaScript virtual DOM is faster than the regular DOM. We can use ReactJS on the client and server-side as well as with other frameworks. It uses component and data patterns that improve readability and helps to maintain larger apps.

Reference:

↥ back to top

Q. How React works?

↥ back to top

Q. List some of the major advantages and limitations of React?

React-Features

Major Advantages:

Limitations:

↥ back to top

Q. Why does React emphasize on unidirectional data flow?

React emphasizes unidirectional data flow (also called “one-way data binding”) because it provides a predictable, easy-to-debug, and modular way to manage how data moves through an application.

In this pattern, data is passed from parent to child components via read-only props. If a child needs to change the data, it doesn't modify it directly; instead, it triggers a callback function provided by the parent to update the “single source of truth”.

Key Benefits

Example:

// Parent controls state
function Parent() {
  const [data, setData] = useState('hello');
  
  return <Child data={data} onChange={setData} />;
}

// Child receives data and callback
function Child({ data, onChange }) {
  return <input value={data} onChange={(e) => onChange(e.target.value)} />;
}
↥ back to top

Q. What is Destructuring in React.js?

Destructuring in React.js is a JavaScript ES6 feature that allows you to extract values from arrays or properties from objects into distinct variables. In React, it is widely used to make code cleaner and more readable.

Key Uses in React:

1. Props Destructuring:

// Without destructuring
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// With destructuring
function Welcome({ name, age }) {
  return <h1>Hello, {name}, you are {age} years old</h1>;
}

2. State Destructuring with Hooks:

// Array destructuring with useState
const [counter, setCounter] = React.useState(0);
const [name, setName] = React.useState("John");

// Object destructuring with useContext
const { user, theme } = useContext(AppContext);

3. Nested Object Destructuring:

const user = {
  name: "Alice",
  address: {
    city: "New York",
    country: "USA"
  }
};

// Destructure nested properties
const { name, address: { city } } = user;
// name = "Alice", city = "New York"

4. Class Component State:

class App extends React.Component {
  render() {
    const { isLoggedIn, user } = this.state;
    return <div>{isLoggedIn ? user.name : "Guest"}</div>;
  }
}
↥ back to top

Q. Why is it necessary to start component names with a capital letter?

In React, component names must start with a capital letter because of how JSX distinguishes between HTML elements and React components:

Key Reasons:

1. JSX Compilation Behavior:

2. Built-in vs Custom Components:

3. Exception:

Lowercase with dot notation works: <obj.component /> compiles to React.createElement(obj.component)

Example:

// ❌ Wrong - React treats this as HTML <mybutton> tag
function myButton() {
  return <button>Click me</button>;
}

// Using it: <myButton /> // Won't work as expected

// ✅ Correct - React treats this as a component
function MyButton() {
  return <button>Click me</button>;
}

// Using it: <MyButton /> // Works correctly
↥ back to top

Q. What are fragments?

React Fragments are a way to group multiple elements without adding an extra node to the browser's DOM.

Why use Fragments?

Example:

// Long syntax
import React, { Fragment } from 'react';

function MyComponent() {
  return (
    <Fragment>
      <h1>Title</h1>
      <p>Description</p>
    </Fragment>
  );
}

// Short syntax (more common)
function MyComponent() {
  return (
    <>
      <h1>Title</h1>
      <p>Description</p>
    </>
  );
}
↥ back to top

Q. What is Virtual DOM?

The Virtual DOM is a programming concept where a “virtual” representation of a User Interface is kept in memory and synchronized with the “real” browser DOM by a library like ReactDOM

How it works:

1. Initial Render: React creates a lightweight tree of JavaScript objects (the Virtual DOM) that mirrors the structure of the real DOM.

2. State Change: When a component's state or props change, React creates a new Virtual DOM tree.

3. Diffing: React compares the new tree with the previous version to identify exactly what changed. This is handled by a highly efficient diffing algorithm.

4. Reconciliation: Based on the “diffs,” React calculates the minimal set of changes needed and updates only those specific parts in the real DOM.

Benefits:

Example:

// When count changes from 0 to 1
const [count, setCount] = useState(0);

return <div>Count: {count}</div>;

React only updates the text node containing the count value, not the entire <div> element.

Virtual DOM Example

↥ back to top

Q. What is the difference between ShadowDOM and VirtualDOM?

DOM

1. Document Object Model:

It a way of representing a structured document via objects. It is cross-platform and language-independent convention for representing and interacting with data in HTML, XML, and others. Web browsers handle the DOM implementation details, so we can interact with it using JavaScript and CSS.

2. Virtual DOM:

Virtual DOM is any kind of representation of a real DOM. Virtual DOM is about avoiding unnecessary changes to the DOM, which are expensive performance-wise, because changes to the DOM usually cause re-rendering of the page. It allows to collect several changes to be applied at once, so not every single change causes a re-render, but instead re-rendering only happens once after a set of changes was applied to the DOM.

3. Shadow DOM:

Shadow DOM is mostly about encapsulation of the implementation. A single custom element can implement more-or-less complex logic combined with more-or-less complex DOM. Shadow DOM refers to the ability of the browser to include a subtree of DOM elements into the rendering of a document, but not into the main document DOM tree.

Difference:

The virtual DOM creates an additional DOM. The shadow DOM simply hides implementation details and provides isolated scope for web components.

Virtual DOM is about performance (efficiently updating the UI), while Shadow DOM is about encapsulation (isolating component styles and structure from the rest of the page).

Note:

React uses Virtual DOM but doesn't use Shadow DOM by default.

↥ back to top

# 2. REACT SETUP


Q. How to set up a react project with Vite?

Vite is a modern, fast build tool that provides a superior development experience compared to traditional bundlers. It offers instant server start, lightning-fast Hot Module Replacement (HMR), and optimized builds.

It replaces older tools like Create React App by providing a leaner, faster build process

Requirements:

Installation:

npm create vite@latest my-react-app -- --template react   #Initialize the Project
cd my-react-app
npm install   #Install Dependencies
npm run dev   #Start the Development Server

Essential Vite Commands:

npm run dev     #Starts the development server with Hot Module Replacement (HMR).
npm run build   #Creates an optimized production bundle in the /dist folder.
npm run preview #Locally previews the production build you just created.

Available Templates:

Project Structure:

my-react-app
├── node_modules
├── public
   └── vite.svg
├── src
   ├── assets
      └── react.svg
   ├── App.css
   ├── App.jsx
   ├── index.css
   └── main.jsx
├── .gitignore
├── index.html
├── package.json
├── vite.config.js
└── README.md

Key Differences from Create React App:

Reference:

↥ back to top

Q. What are the features of Vite?

Vite is a modern build tool and development server with these key features:

Core Features

Optimized Production Build

Rich Features

↥ back to top

1. ESLint:

ESLint is a popular JavaScript linter. There are plugins available that analyse specific code styles. One of the most common for React is an npm package called eslint-plugin-react.

npm install -g eslint-plugin-react

This will install the plugin we need, and in our ESLint config file, we just need a few extra lines.

"extends": [
    "eslint:recommended",
    "plugin:react/recommended"
]
"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject",
    "lint": "eslint src/**/*.js src/**/*.jsx"
}

2. eslint-plugin-jsx-a11y:

3. Other Popular Options:

↥ back to top

Q. What is the browser support for react applications?

React applications are supported by all modern web browsers. Because React uses JavaScript ES5 features as its baseline, it can be extended to older browsers with the right configuration.

Support for Internet Explorer 9, 10, and 11 requires polyfills. For a set of polyfills to support older browsers, use react-app-polyfill.

Browser Configuration:

The browserslist configuration in package.json controls which browsers are supported by determining what JavaScript transformations are applied:

Example:

// package.json

"browserslist": {
  "production": [
    ">0.2%",          // Browsers with >0.2% market share
    "not dead",       // Still maintained browsers
    "not op_mini all" // Exclude Opera Mini
  ],
  "development": [
    "last 1 chrome version",
    "last 1 firefox version",
    "last 1 safari version"
  ]
}
↥ back to top

Q. Explain the use of Webpack and Babel in React?

1. Webpack (The Transpiler):

Webpack primary job is to take all your individual files (JavaScript, CSS, images) and “bundle” them into a few optimized files.

2. Babel (The Module Bundler):

Babel is a “translator” that converts modern code into a version that all browsers can understand.

How they work together:

↥ back to top

Q. What is ReactDOM?

ReactDOM is a package that provides DOM-specific methods for managing DOM elements in web applications. It serves as the bridge between React components and the browser's DOM.

ReactDOM provides the developers with an API containing the following methods

Key Methods (React 18+):

Note:

ReactDOM.render(), ReactDOM.hydrate(), ReactDOM.unmountComponentAtNode(), and ReactDOM.findDOMNode() are deprecated as of React 18. Use the react-dom/client APIs instead.

Syntax:

import { createRoot, hydrateRoot } from 'react-dom/client';
import { createPortal } from 'react-dom';

const root = createRoot(container);   // createRoot()
root.render(element);                 // render()
root.unmount();                       // unmount()

hydrateRoot(container, element);      // hydrateRoot() — replaces hydrate()

createPortal(child, container);       // createPortal()

Example:

import { createRoot } from 'react-dom/client';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(<App />);
↥ back to top

Q. What is the difference between ReactDOM and React?

React is the core library that contains the fundamental React functionality used across all platforms (web, mobile, etc.)

ReactDOM is a separate package that provides DOM-specific methods for web applications - it's the bridge between React components and the browser's DOM.

Key Differences:

React ReactDOM
It is core engine. It manages component logic, state, hooks, and props. The web renderer. It translates React components into actual HTML DOM nodes.
It is used for Creating the Virtual DOM (a blueprint of what the UI should look like). Updating the Real DOM (the actual elements visible in the browser).
It is Platform-independent; used for Web, Mobile, VR, etc. Browser-specific; used only for web applications.
useState, useEffect, createElement, Component. createRoot, createPortal, hydrateRoot.

Example:

/**
 * React vs ReactDOM
 */
import React from 'react';                      // Core functionality
import { createRoot } from 'react-dom/client';  // DOM rendering

export default function App() {
  return <h1>Hello React</h1>;
}

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(<App />);

Try this example on CodeSandbox

↥ back to top

Q. How to build a progressive web app with react?

A Progressive Web App (PWA) is a web application that uses modern web capabilities to deliver an app-like experience to users. React applications can be converted into PWAs by adding service workers, manifest files, and implementing offline capabilities.

Building a Progressive Web App (PWA) with React is mostly about adding a web app manifest, a service worker (for Offline, Caching, and updates), and meeting installability criteria (HTTPS, icons, etc).

Steps to Build a PWA with React:

1. Vite with PWA Template:

Vite offers a modern approach for building PWAs using the vite-plugin-pwa package.

# Create new React app with PWA template
npm create vite@latest my-pwa-app -- --template react
cd my-pwa-app
npm install

npm install vite-plugin-pwa -D # Install the PWA package

2. Registering the Service Worker:

The Service Worker manage tasks between browser and server, intercepting network requests, managing caching, and providing offline functionality.

Basic Service Worker Registration:

Add this code to your src/main.jsx file:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

// Service Worker registration
if ('serviceWorker' in navigator) {
  // Check if browser supports Service Worker
  window.addEventListener('load', () => {
    // Execute after page is fully loaded
    navigator.serviceWorker.register('/sw.js')
      .then(registration => {
        console.log('SW registered: ', registration);
        // Registration successful
      })
      .catch(registrationError => {
        console.log('SW registration failed: ', registrationError);
        // Registration failed
      });
  });
}

3. Configuring the Manifest File:

Modify your vite.config.js to include and configure the plugin, specifying manifest and service worker options.

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      registerType: 'autoUpdate',  // Automatically update Service Worker
      includeAssets: ['favicon.ico', 'robots.txt', 'apple-touch-icon.png'],  // Files to cache
      manifest: {
        name: 'My First PWA',  // Full app name
        short_name: 'PWA App',  // Short name displayed on home screen
        description: 'My first Progressive Web App built with React',
        theme_color: '#ffffff',  // Color of the top bar
        background_color: '#ffffff',  // Splash screen background color
        display: 'standalone',  // Makes it look like a native app (hides browser UI)
        icons: [
          {
            src: 'pwa-192x192.png',  // Small icon
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',  // Large icon
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any maskable'  // Works in various environments
          }
        ]
      }
    })
  ]
})

Key PWA Features:

Reference:

↥ back to top

Q. What is the difference between vite and webpack?

The primary difference between Vite and Webpack is how they handle code during development. While Webpack bundles your entire application before serving it, Vite serves individual files directly to the browser using modern web standards.

Key Differences:

Webpack:

Webpack is a module bundler that:

Vite:

Example: Webpack Configuration (Manual Setup)

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ],
  devServer: {
    port: 3000,
    hot: true
  }
};

Example: Vite (Zero Configuration)

# Just one command!
npx create-react-app my-app
cd my-app
npm start

When to Use Webpack:

When to Use Vite:

↥ back to top

# 3. REACT JSX


Q. What is JSX?

JSX (JavaScript XML) is a syntax extension that allows you to write HTML-like code directly in JavaScript. It is used in React to describe what the UI should look like.

JSX is not required for React, but it makes code more readable and easier to write. Under the hood, it's just syntactic sugar for React.createElement() calls.

Key Points:

Example:

// JSX syntax
const hello = <h1 className="greet">Hello World</h1>

// Compiles to:
const hello = React.createElement("h1", {
  className: "greet"
}, "Hello World")

In a component:

export default function App() {
  return (
    <div className="App">
      <h1>Hello World!</h1>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How JSX prevents Injection Attacks?

JSX prevents injection attacks, specifically Cross-Site Scripting (XSS), by automatically escaping any values embedded within JSX elements before they are rendered to the DOM. This means all dynamic content is converted into plain strings, neutralizing potentially malicious code.

Example:

export default class JSXInjectionExample extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      userContent: `JSX prevents Injection Attacks Example 
          <script src="http://example.com/malicious-script.js></script>`
    };
  }

  render() {
    return (
      <div>User content: {this.state.userContent}</div>
    );
  }
}

// Output
User content: JSX prevents Injection Attacks Example 
<script src="http://example.com/malicious-script.js></script>

Try this example on CodeSandbox

↥ back to top

Q. What are the benefits of new JSX transform?

The new JSX transform, React 19, provides several key benefits for developers and application performance

↥ back to top

Q. Is it possible to use React without rendering HTML?

It is possible with latest version (>=16.2). Below are the possible options:

// 1. Return false
render() {
  return false
}

// 2. Return null (most common)
render() {
  return null
}

// 3. Return empty array
render() {
  return []
}

// 4. Return empty Fragment (long syntax)
render() {
  return <React.Fragment></React.Fragment>
}

// 5. Return empty Fragment (short syntax)
render() {
  return <></>
}

Note:

React can also run on the server side so, it will be possible to use it in such a way that it doesn't involve any DOM modifications (but maybe only the virtual DOM computation).

↥ back to top

Q. How to write comments in React and JSX?

Writing comments in React components can be done just like comment in regular JavaScript classes and functions.

React comments:

function App() {

  // Single line Comment

  /*
  * multi
  * line
  * comment
  **/

  return (
    <h1>My Application</h1>
  );
}

JSX comments:

export default function App() {
  return (
    <div>
      {/* A JSX comment */}
      <h1>My Application</h1>
    </div>
  );
}
↥ back to top

Q. How to add custom DOM attributes in JSX?

Custom attributes are supported natively in React 16+. This means that adding a custom attribute to an element is now as simple as adding it to a render function, like so:

Syntax:

// 1. Custom DOM Attribute
render() {
  return (
    <div custom-attribute="some-value" />
  );
}

// 2. Data Attribute ( starts with "data-" )
render() {
  return (
    <div data-id="10" data-user-role="admin"/>
  );
}

// 3. ARIA Attribute ( starts with "aria-" )
render() {
  return (
    <button aria-label="Close" onClick={onClose} />
  );
}

Example:

function CustomAttributeExample() {
  return (
    <div
      custom-attribute="custom-value"
      data-testid="my-component"
      data-category="widgets"
      aria-label="Product information"
    >
      Content with custom attributes
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How many outermost elements can be there in a JSX expression?

A JSX expression must have only one outer element. For Example:

const headings = (
    <div id = "outermost-element">
       <h1>I am a heading </h1>
       <h2>I am also a heading</h2>
    </div>
)
↥ back to top

Q. How to loop inside JSX?

To loop inside JSX, use the Array.prototype.map() method with ES6 arrow functions. This is the standard React pattern for rendering lists of elements.

Example:

/**
 * Loop inside JSX
 */
const items = ['Apple', 'Banana', 'Cherry'];

function FruitList() {
  return (
    <ul>
      {items.map((item) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How do you print false values in JSX?

In React, boolean values (true and false), null, and undefined are valid children, but these values will not be rendered in UI if you put them directly inside {} in JSX.

For example, all these JSX expressions will result in the same empty div:

<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>

If you want a value like false, true, null, or undefined to show in the output, you have to convert it to a string first.

<div>{String(true)}</div>
<div>{String(false)}</div>
<div>{String(undefined)}</div>
<div>{String(null)}</div>

In the output, this will render true, false, undefined, and null respectively.

Try this example on CodeSandbox

↥ back to top

Q. How to use React label element?

In React, you cannot use the standard HTML for attribute with <label> elements because for is a reserved keyword in JavaScript. Instead, React uses htmlFor.

❌ Wrong - Using for (produces warning):

<label for={'user'}>{'User'}</label>
<input type={'text'} id={'user'} />

✅ Correct - Using htmlFor:

<label htmlFor={'user'}>{'User'}</label>
<input type={'text'} id={'user'} />

Example:

function LoginForm() {
  return (
    <div>
      <label htmlFor="username">Username:</label>
      <input type="text" id="username" name="username" />
      
      <label htmlFor="password">Password:</label>
      <input type="password" id="password" name="password" />
    </div>
  );
}
↥ back to top

Q. How to use InnerHtml in React?

The innerHTML is risky because it is easy to expose users to a cross-site scripting (XSS) attack. React provides dangerouslySetInnerHTML as a replacement for innerHTML. It allows to set HTML directly from React by using dangerouslySetInnerHTML and passing an object with a __html key that holds HTML.

Example:

/**
 * InnerHtml in React
 */
export default function App() {
  return (
    <div
      dangerouslySetInnerHTML=
    ></div>
  );
}

Example: Using sanitization

import DOMPurify from 'dompurify';

function SafeHTML({ html }) {
  const sanitizedHTML = DOMPurify.sanitize(html);
  
  return (
    <div dangerouslySetInnerHTML= />
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to show and hide elements in React?

1. Returning Null:

const AddToCart = ({ available }) => {
  if (!available) return null

  return (
    <div className="full tr">
      <button className="product--cart-button">Add to Cart</button>
    </div>
  )
}

2. Ternary Display:

When you need to control whether one element vs. another is displayed, or even one element vs. nothing at all (null), you can use the ternary operator embedded inside of a larger portion of JSX.

<div className="half">
  <p>{description}</p>

  {remaining === 0 ? (
    <span className="product-sold-out">Sold Out</span>
  ) : (
    <span className="product-remaining">{remaining} remaining</span>
  )}
</div>

In this case, if there are no products remaining, we will display “Sold Out”; otherwise we will display the number of products remaining.

3. Shortcut Display:

It involves using a conditional inside of your JSX that looks like checkIfTrue && <span>display if true</span>. Because if statements that use && operands stop as soon as they find the first value that evaluates to false, it won't reach the right side (the JSX) if the left side of the equation evaluates to false.

<h2>
  <span className="product--title__large">{nameFirst}</span>
  {nameRest.length > 0 && (
    <span className="product--title__small">{nameRest.join(" ")}</span>
  )}
</h2>

4. Using Style Property:

<div style=>info</div>
↥ back to top

# 4. REACT COMPONENTS


Q. What are React components?

React components are the essential building blocks of a React application. They are independent, reusable pieces of code that serve the same purpose as JavaScript functions but work in isolation to return UI elements.

Two Main Types:

1. Stateless Component:

const Welcome = (props) => {
    return <h1>Hello, {props.name}</h1>;
};

const App = () => {
  const name = 'React'
  return (
    <div>
      <Welcome name={name} />
    </div>
  );
};

export default App;

The above example shows a stateless component named Welcome which is inserted in the <App/> component. The Welcome just comprises of a <h1> element. Although the Stateless component has no state, it still receives data via props from a parent component.

2. Stateful Component:

import React, { useState } from 'react'

const ExampleComponent = (props) => {
  const [email, setEmail] = useState(props.defaultEmail) // state

  const changeEmailHandler = (e) => {
    setEmail(e.target.value)
  }

  return (
    <input type="text" value={email} onChange={changeEmailHandler} />
  );
}


const App = () => {
  const defaultEmail = "suniti.mukhopadhyay@gmail.com"
  return (
    <div>
      <ExampleComponent defaultEmail={defaultEmail} />
    </div>
  );
};

export default App;

The above example shows a stateful component named ExampleComponent which is inserted in the <App/> component. The ExampleComponent contains a <input>. First of all, in the ExampleComponent, we need to assign defaultEmail by props to a local state by a useState() hook in ExampleComponent.

Next, we have to pass email to value property of a input tag and pass a function changeEmailHandler to an onChange() event for a purpose keeping track of the current value of the input.

↥ back to top

Q. What is the difference between Component and Container in React?

In React, the “Component” (specifically a “Presentational” component) vs. “Container” distinction refers to a popular design pattern used to separate logic from presentation. While every “Container” is technically a React component, they serve different architectural roles.

Presentational Components:

Container Components:

Example: Presentational Component

/**
 * Presentational Component 
 */
const Users = props => (
  <ul>
    {props.users.map(user => (
      <li>{user}</li>
    ))}
  </ul>
)

Example: Container Component

/**
 * Container Component 
 */
class UsersContainer extends React.Component {
  constructor() {
    this.state = {
      users: []
    }
  }

  componentDidMount() {
    axios.get('/users').then(users =>
      this.setState({ users: users }))
    )
  }

  render() {
    return <Users users={this.state.users} />
  }
}
↥ back to top

Q. How to import and export components using React.js?

React components are typically separated into individual files to keep code modular and manageable. React uses standard JavaScript ES6 module syntax for this purpose, primarily utilizing Default and Named exports

1. Default Export and Import (Recommended):

Use a default export when a file exports only one primary component.

Example:

// Button.js
export default function Button() {
  return <button>Click me</button>;
}

// Or with class components
class Button extends Component {
  render() {
    return <button>Click me</button>;
  }
}
export default Button;

// App.js
import MyButton from './Button'; // No curly braces; can rename 'Button' to 'MyButton'

2. Named Export and Import

Use named exports when you want to export multiple components or values from a single file.

Example:

// Components.js
export function Header() { return <h1>Header</h1>; }
export function Footer() { return <footer>Footer</footer>; }

// App.js
import { Header, Footer } from './Components'; // Must use exact names

Key Differences

Default Export Named Export
One per file Multiple per file
Import with any name Import with exact name (or rename with as)
export default Component export { Component }
import Component from './file' import { Component } from './file'
↥ back to top

Q. What is difference between declarative and imperative in React.js?

The main difference is that imperative programming focuses on how to perform a task using explicit, step-by-step instructions, while declarative programming (which React uses) focuses on what the desired outcome should be, and lets the system figure out the how.

1. Declarative programming:

In React, you simply describe what the UI should look like for a given state, and React handles updating the DOM efficiently. You don't manually manipulate DOM elements—you declare the desired outcome and React takes care of the “how.”

This makes React code more:

Example:

/**
 * React is Declarative
 */
const Welcome = () => (
  <div id="App">
    <h1>Hello World</h1>
  </div>
)

render(<Welcome />, document.getElementById('root'))

2. Imperative programming:

Imperative programming requires you to write a sequence of commands that explicitly change the program's state step-by-step. This is common in vanilla JavaScript when directly manipulating the DOM.

/**
 * vanilla JavaScript
 */
const string = "Hi there, I'm a web developer";
let removeSpace = "";

for (let i = 0; i < i.string.length; i++) {
  if (string[i] === " ") removeSpace += "-";
  else removeSpace += string[i]; 
}
console.log(removeSpace);

This example demonstrates imperative programming by looping through each character and replacing spaces one by one. The code requires extensive comments to convey its intent—without them, the logic is difficult to understand.

In contrast, declarative programming uses self-documenting syntax that clearly expresses the desired outcome while abstracting away the implementation details.

↥ back to top

Q. What is the difference between Element and Component?

1. React Element:

It is a simple object that describes a DOM node and its attributes or properties. It is an immutable description object and you can not apply any methods on it.

Example:

const element = <h1>React Element Example!</h1>;
ReactDOM.render(element, document.getElementById('app'));

2. React Component:

A React Component is a function or class that accepts inputs (props) and returns a React element. It keeps references to DOM nodes and child component instances.

Example:

function Message() {
  return <h2>React Component Example!</h2>;
}
ReactDOM.render(<Message />, document.getElementById('app'));

Key Differences:

React Element React Component  
  A plain JavaScript object. A function or a class.
  Describes what to see on screen. Defines how to build the UI and logic.
  Immutable (cannot be changed). Dynamic (can change via state/props).
  No Input (it is the data). Accepts “Props” as arguments.
  No lifecycle Has hooks (useEffect) and lifecycle.
↥ back to top

Q. How to conditionally render components in react?

Conditional rendering is a term to describe the ability to render different user interface (UI) markup if a condition is true or false. In React, it allows us to render different elements or components based on a condition.

1. if/else Statements (and Element Variables):

You can use variables to store elements. This can help you conditionally render a part of the component while the rest of the output doesn't change.

Example:

import { createRoot } from 'react-dom/client';

function LogInComponent({ isLoggedIn }) {
  if (isLoggedIn) {
    return <UserComponent />;
  }
  return <GuestComponent />;
}

const root = createRoot(document.getElementById('root'));
root.render(<LogInComponent isLoggedIn={false} />);

2. Ternary Operator(? :)

The ternary operator is a concise way to handle an if/else condition inline within JSX. It is ideal for simple, two-option conditions.

Example:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn
        ? <LogoutButton onClick={this.handleLogoutClick} />
        : <LoginButton onClick={this.handleLoginClick} />
      }
    </div>
  );
}

3. Logical AND Operator (&&)

The logical && operator is useful when you want to render something only if a condition is true, and render nothing otherwise.

Example:

function Messages({ messageCount }) {
  return (
    <div>
      {messageCount > 0 && <h2>You have {messageCount} new messages.</h2>}
    </div>
  );
}

4. switch Statements

For scenarios with multiple conditions, a switch statement can be cleaner and more readable than a long chain of if/else if statements.

Example:

function StatusMessage({ status }) {
  const renderContent = () => {
    switch (status) {
      case 'loading':
        return <p>Loading...</p>;
      case 'success':
        return <p>Data loaded successfully!</p>;
      case 'error':
        return <p>Error fetching data.</p>;
      default:
        return null;
    }
  };

  return <div>{renderContent()}</div>;
}

5. Returning null to Prevent Rendering

To hide a component, you can have it return null. This prevents the component from rendering any output, although its lifecycle methods (like componentDidUpdate) still fire.

Example:

function WarningBanner({ showWarning }) {
  if (!showWarning) {
    return null;
  }
  return <div>Warning!</div>;
}

Try this example on CodeSandbox

↥ back to top

Q. How to conditionally add attributes to React components?

In React, you can conditionally add attributes using several JavaScript patterns within your JSX. The most common methods include

1. Ternary Operator

Use this for toggling between two values or between a value and undefined. React will completely omit an attribute if its value is undefined, null, or false.

<button disabled={isLoading ? true : false}>
  Submit
</button>

// Simplified for boolean attributes
<button disabled={isLoading}>Submit</button>

2. Logical AND Operator

<input 
  type="text"
  {...(isRequired && { required: true })}
  {...(maxLength && { maxLength: maxLength })}
/>

3. for Custom Data Attributes

function DataComponent({ mood, role }) {
  return (
    <div
      data-mood={mood === 'happy' ? 'positive' : 'neutral'}
      data-role={role || undefined}
      aria-disabled={mood === 'sad'}
    >
      Content
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How would you prevent a component from rendering?

There are several ways to prevent a component from rendering in React:

1. Return null

A component can return null from its render function to signify it should render nothing.

function MyComponent({ isVisible }) {
  if (!isVisible) {
    return null;
  }
  return <div>Content</div>;
}

2. Conditional Rendering:

function Parent() {
  return (
    <div>
      {condition && <MyComponent />}  {/* Short-Circuit Evaluation */}
      {condition ? <MyComponent /> : null} {/* Ternary Operator */}
    </div>
  );
}

3. React.memo: (Functional Components)

Wraps your component to memoize it. It will only re-render if its props actually change.

const MyComponent = React.memo(({ value }) => {
  return <div>{value}</div>;
});

4. shouldComponentUpdate() (Class Components)

Control when component updates:

class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.value !== this.props.value;
  }
  
  render() {
    return <div>{this.props.value}</div>;
  }
}

5. useMemo() Hook

Memoize the entire component output:

function Parent({ data }) {
  const memoizedComponent = useMemo(() => {
    return <ExpensiveComponent data={data} />;
  }, [data]);
  
  return memoizedComponent;
}

Try this example on CodeSandbox

↥ back to top

Q. When would you use StrictMode component in React?

StrictMode is a development tool that helps identify bugs and outdated code during the development phase. It is a wrapper tool that enables additional runtime checks and warnings for its child components without affecting the production build.

Example:

/**
 * StrictMode
 */
import { StrictMode } from "react";
import MyComponent from "./MyComponent";

export default function App() {
  return (
    <StrictMode>
      <MyComponent />
    </StrictMode>
  );
}

React StrictMode, in order to be efficient and avoid potential problems by any side-effects, needs to trigger some methods and lifecycle hooks twice. These are:

Benefits of StrictMode:

↥ back to top

Q. Why to avoid using setState() after a component has been unmounted?

In React, calling setState() on an unmounted component should be avoided primarily because it signals a potential memory leak in your application.

The component retains references in memory even after unmounting, preventing garbage collection. Subscriptions, timers, or async operations holding references to the component keep it alive unnecessarily

Warning Messages:

Warning: Can not perform a React state update on an unmounted component. 
This is a no-op, but it indicates a memory leak in your application.

Prevention:

Use cleanup in useEffect():

useEffect(() => {
  let isMounted = true;
  
  fetchData().then(data => {
    if (isMounted) {
      setState(data);
    }
  });
  
  return () => {
    isMounted = false; // Cleanup
  };
}, []);

The warning indicates a logic flaw where side effects aren't properly cleaned up, which can lead to performance issues and unexpected behavior in larger applications.

Try this example on CodeSandbox

↥ back to top

Q. What is Lifting State Up in ReactJS?

In React, “Lifting State Up” is a pattern where you move state from child components to their closest common parent component so that multiple children can share and sync the same data.

Instead of each component managing its own copy of the data, the parent component becomes the “single source of truth”

Example:

The code shows an App component that manages player selection state and passes it down to:

When a button is clicked in PlayerContent, it calls updateSelectedPlayer() in the parent App, which updates state that both components depend on. This keeps both components synchronized with the same player selection.

/**
 * Lifting State Up
 */

import PlayerContent from "./PlayerContent";
import PlayerDetails from "./PlayerDetails";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { selectedPlayer: [0, 0], playerName: "" };
    this.updateSelectedPlayer = this.updateSelectedPlayer.bind(this);
  }
  updateSelectedPlayer(id, name) {
    const arr = [0, 0, 0, 0];
    arr[id] = 1;
    this.setState({
      playerName: name,
      selectedPlayer: arr
    });
  }
  render() {
    return (
      <div>
        <PlayerContent
          active={this.state.selectedPlayer[0]}
          clickHandler={this.updateSelectedPlayer}
          id={0}
          name="Player 1"
        />
        <PlayerContent
          active={this.state.selectedPlayer[1]}
          clickHandler={this.updateSelectedPlayer}
          id={1}
          name="Player 2"
        />
        <PlayerDetails name={this.state.playerName} />
      </div>
    );
  }
}
/**
 * PlayerContent
 */
import React, { Component } from "react";

export default class PlayerContent extends Component {
  render() {
    return (
      <button
        onClick={() => {
          this.props.clickHandler(this.props.id, this.props.name);
        }}
        style=
      >
        {this.props.name}
      </button>
    );
  }
}
/**
 * PlayerDetails
 */
import React, { Component } from "react";

export default class PlayerDetails extends Component {
  render() {
    return <h2>{this.props.name}</h2>;
  }
}

Try this example on CodeSandbox

↥ back to top

Q. What is “Children” in React?

In React, children is a special prop that allows you to pass components, elements, or any content between the opening and closing tags of a component.

Example:

// Component that uses children
const Picture = (props) => {
  return (
    <div>
      <img src={props.imageUrl} />
      {props.children}  {/* Displays whatever is passed between tags */}
    </div>
  )
}

// Using the component with children
render() {
  return (
    <div className='container'>
      <Picture imageUrl="photo.jpg">
        <h2>Image Title</h2>
        <p>Image description here</p>
      </Picture>
    </div>
  )
}

In this example, the <h2> and <p> elements are the “children” of the <Picture> component. They're passed down and rendered wherever {props.children} appears in the Picture component.

↥ back to top

Q. What is Compound Components in React?

Compound Components is an advanced React design pattern where multiple components work together to form a cohesive unit while sharing an implicit state.

How It Works:

Compound components use React's lower-level APIs:

Example:

function App() {
  return (
    <Menu>
      <MenuButton>Actions</MenuButton>
      <MenuList>
        <MenuItem>Download</MenuItem>
        <MenuItem>Create</MenuItem>
        <MenuItem>Delete</MenuItem>
      </MenuList>
    </Menu>
  )
}

In this example, the <Menu> establishes some shared implicit state. The <MenuButton>, <MenuList>, and <MenuItem> components each access and/or manipulate that state, and it's all done implicitly. This allows you to have the expressive API you’re looking for.

↥ back to top

# 4.1. FUNCTIONAL COMPONENTS


Q. What are functional components in react?

A React functional component is a simple JavaScript function that accepts props and returns a React element. It also referred as stateless components as it simply accept data and display them in some form.

After the introduction of React Hooks, writing functional components has become the ​standard way of writing React components in modern applications.

Example:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Usage
const element = <Welcome name="World!" />;

With Hooks:

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // State management via Hook
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

# 4.2. CLASS COMPONENTS


Q. What are class components in react?

Class components are stateful/container components that are regular ES6 classes extending React.Component. They're called stateful components because they:

Example:

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = { message: "Hello!" };
  }

  render() {
    return <h1>{this.state.message} {this.props.name}</h1>;
  }
}

When to Use:

Try this example on CodeSandbox

↥ back to top

This ordering helps maintain consistency and readability in your class components by grouping related methods together: lifecycle methods first, then event handlers, helper methods, and finally the render method at the bottom.

↥ back to top

Q. How to create a dynamic table in react?

/**
 * Generate dynamic table in React
 */
class Table extends React.Component {
   constructor(props) {
      super(props)
      this.state = {
         employees: [
            { id: 10, name: 'Swarna Sachdeva', email: 'swarna@email.com' },
            { id: 20, name: 'Sarvesh Date', email: 'sarvesh@email.com' },
            { id: 30, name: 'Diksha Meka', email: 'diksha@email.com' }
         ]
      };
   }

   renderTableHeader() {
      let header = Object.keys(this.state.employees[0])
      return header.map((key, index) => {
         return <th key={index}>{key.toUpperCase()}</th>
      })
   }

   renderTableData() {
      return this.state.employees.map((employee, index) => {
         const { id, name, email } = employee 
         return (
            <tr key={id}>
               <td>{id}</td>
               <td>{name}</td>
               <td>{email}</td>
            </tr>
         )
      })
   }

   render() {
      return (
        <div>
          <h1>Employee Records</h1>
          <table>
            <thead>
              <tr>{this.renderTableHeader()}</tr>
            </thead>
            <tbody>{this.renderTableData()}</tbody>
          </table>
        </div>
      )
   }
}

Try this example on CodeSandbox

↥ back to top

Q. How do you set a timer to update every second in React.js?

In React.js, the most reliable way to set a timer that updates every second is by using the useEffect() and useState() hooks together.

Core Implementation:

To ensure your timer starts correctly and doesn't cause memory leaks, follow these three steps:

Example: Counting Up Every Second

import { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    // 1. Set the interval to 1000ms (1 second)
    const interval = setInterval(() => {
      // Use functional update to avoid closure issues with 'seconds'
      setSeconds(prev => prev + 1);
    }, 1000);

    // 2. Clean up the interval on unmount
    return () => clearInterval(interval);
  }, []); // Empty array ensures this only runs once

  return <div>Time elapsed: {seconds} seconds</div>;
}
↥ back to top

Q. Differentiate between stateful and stateless components?

1. Stateless Components (Presentational)

Stateless components are simple functions that receive data and return what should be rendered. They do not have an internal “memory.”

2. Stateful Components (Container)

Stateful components manage and track their own internal data (state), which can change based on user interaction or API responses.

Example: Stateless/Presentational/Dumb component

import React from 'react';

// This is stateless: it just takes a name and displays it.
const Greeting = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

export default Greeting;

Example: Stateful/Container/Smart component

import React, { useState } from 'react';

const ClickCounter = () => {
  // 'count' is the state, 'setCount' is the function to update it.
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
};

export default ClickCounter;

Quick Comparison Table:

Feature Stateless Components Stateful Components
Internal State No Yes
Knowledge Knows nothing of the past/future Remembers past changes
Primary Tool props state (and props)
Complexity Simple & lightweight Complex logic-heavy
Testing Easy to test Harder to test
↥ back to top

Q. What is the difference between Element, Component and Component instance in React?

In React, these three concepts represent different levels of abstraction:

1. React Elements:

A React Element is just a plain old JavaScript Object without own methods. It has essentially four properties:

A React Element is not an instance of a React Component. It is just a simplified “description” of how the React Component Instance to be created should look like.

Example:

const element = <h1>Hello</h1>;
// Same as: React.createElement('h1', null, 'Hello')

2. React Components and React Component Instances:

A React Component is used by extending React.Component. If a React Component is instantiated it expects a props Object and returns an instance, which is referred to as a React Component Instance.

A React Component can contain state and has access to the React Lifecycle methods. It must have at least a render method, which returns a React Element(-tree) when invoked.

Example:

// Function Component
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Class Component
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
↥ back to top

Q. What does shouldComponentUpdate do and why is it important?

The shouldComponentUpdate() method allows Component to exit the Update life cycle if there is no reason to apply a new render. It receives nextProps and nextState as parameters and returns a boolean.

Example:

shouldComponentUpdate(nextProps, nextState) {
  console.log(nextProps, nextState)
  console.log(this.props, this.state)
  return false  // Prevents re-render
}

Why it is Important

↥ back to top

Q. What is the purpose of render() function in React?

In React, the render() function is a core lifecycle method used primarily in class components to define the visual structure of the user interface (UI). It acts as a “blueprint” that tells React what elements should appear on the screen based on the component's current data

Key purposes:

Example:

/**
 * render() function
 * 
 */
class App extends React.Component {
  render() {
    return <h1>Render() Method Example</h1>;
  }
}

The render() method is called automatically whenever props or state change, causing React to update the DOM with the new output.

Note:

The modern React (v18+), functional components use return directly instead of a render() method, and the actual DOM rendering is done via createRoot().render().

Try this example on CodeSandbox

↥ back to top

# 4.2.1. REACT LIFECYCLE


Q. What are the different phases of React component lifecycle?

React provides several methods that notify us when certain stage of this process occurs. These methods are called the component lifecycle methods and they are invoked in a predictable order. The lifecycle of the component is divided into three main phases.

React component lifecycle

1. Mounting:

These methods are called in the following order when an instance of a component is being created and inserted into the DOM:

2. Updating:

The next phase in the lifecycle is when a component is updated. A component is updated whenever there is a change in the component's state or props.

React has five built-in methods that gets called, in this order, when a component is updated:

3. Unmounting:

The next phase in the lifecycle is when a component is removed from the DOM, or unmounting as React likes to call it.

↥ back to top

Q. How to make component to perform an action only once when the component initially rendered?

1. Using Class Component:

The componentDidMount() lifecycle hook can be used with class components. Any actions defined within a componentDidMount() lifecycle hook are called only once when the component is first mounted.

Example:

class Homepage extends React.Component {
  componentDidMount() {
    trackPageView('Homepage') // Runs only once after first render
  }
  render() {
    return <div>Homepage</div>
  }
}

2. Using Functional Component:

The useEffect() hook can be used with function components. The useEffect() hook is more flexible than the lifecycle methods used for class components. It receives two parameters:

The value passed as the second argument controls when the callback is executed:

Example:

const Homepage = () => {
  useEffect(() => {
    trackPageView('Homepage') // Runs only once after first render
  }, []) // Empty dependency array is the key!
  
  return <div>Homepage</div>
}
↥ back to top

Q. What is the typical pattern for rendering a list of components from an array of data?

The typical pattern for rendering a list of components from an array of data in React is to use the .map() method:

Example:

const fruits = ['Apple', 'Banana', 'Cherry'];

function FruitList() {
  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}
↥ back to top

Q. What is difference between useEffect() vs componentDidMount()?

In react when we use class based components we get access to lifecycle methods ( like componentDidMount(), `componentDidUpdate(), etc ). But when we want use a functional component and also we want to use lifecycle methods, then using useEffect() we can implement those lifecycle methods.

1. componentDidMount():

The componentDidMount() and useEffect() run after the mount. However useEffect() runs after the paint has been committed to the screen as opposed to before. This means we would get a flicker if needed to read from the DOM, then synchronously set state to make new UI.

The useLayoutEffect() was designed to have the same timing as componentDidMount(). So useLayoutEffect(fn, []) is a much closer match to componentDidMount() than useEffect(fn, []) – at least from a timing standpoint.

/**
 * componentDidMount() in Class Component
 */
import React, { Component } from "react";

export default class SampleComponent extends Component {
  componentDidMount() {
    // code to run on component mount
  }
  render() {
    return <>componentDidMount Example</>;
  }
}

2. useEffect():

/**
 * useEffect() in Functional Component
 */
import React, { useEffect } from "react";

const SampleComponent = () => {
  useEffect(() => {
    // code to run on component mount
  }, []);
  return <>useEffect Example</>;
};
export default SampleComponent;

When useEffect() is used to get data from server.

↥ back to top

Q. Why is a component constructor called only once?

React's reconciliation algorithm assumes that without any information to the contrary, if a custom component appears in the same place on subsequent renders, it's the same component as before, so reuses the previous instance rather than creating a new one.

Key Concept: React uses component position in the tree to determine identity. If a component renders in the same spot, React keeps the same instance alive.

How to Force a New Instance:

If you give each component a unique key prop, React can use the key change to infer that the component has actually been substituted and will create a new one from scratch, giving it the full component lifecycle.

Example:

renderContent() {
  if (this.state.activeItem === 'item-one') {
    return (
      <ComponentA title="First" key="first" />
    )
  } else {
    return (
      <ComponentA title="Second" key="second" />
    )
  }
}

When the key changes, React recognizes it as a different component and will:

This is why constructors are called only once per component instance - React optimizes by reusing instances when possible, unless you explicitly signal otherwise with the key prop.

↥ back to top

Q. What is difference between componentDidMount() and componentWillMount()?

componentDidMount():

The componentDidMount() is executed after the first render only on the client side. This is where AJAX requests and DOM or state updates should occur. This method is also used for integration with other JavaScript frameworks and any functions with delayed execution such as setTimeout() or setInterval().

Example:

class App extends Component {
  componentDidMount() {
    this.getData() // API calls go here
  }
  
  getData() {
    setTimeout(() => {
      this.setState({ data: 'Data loaded!' })
    }, 1000)
  }
}

componentWillMount():

The componentWillMount() method is executed before rendering, on both the server and the client side. componentWillMount() method is the least used lifecycle method and called before any HTML element is rendered. It is useful when we want to do something programmatically right before the component mounts.

Example:

class App extends Component {
  componentWillMount() {
    console.log('First this called') // Runs before render
  }
  
  componentDidMount() {
    this.getData() // Runs after render
  }
}

Note:

componentWillMount() is now deprecated in modern React. You should avoid using it and use componentDidMount() or the constructor() instead for initialization logic.

↥ back to top

Q. Is it good to use setState() in componentWillMount() method?

Avoid async initialization in componentWillMount().

componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-render. Avoid introducing any side-effects or subscriptions in this method.

Make async calls for component initialization in componentDidMount() instead of componentWillMount()

function componentDidMount() {
  axios.get(`api/messages`)
    .then((result) => {
      const messages = result.data
      console.log("COMPONENT WILL Mount messages : ", messages);
      this.setState({
        messages: [...messages.content]
      })
    })
}
↥ back to top

Q. How to use componentWillUnmount() with Functional Components in React?

The useEffect() can be used to manage API calls, as well as implementing componentWillMount(), and componentWillUnmount().

If we pass an empty array as the second argument, it tells useEffect to fire on component load. This is the only time it will fire.

import React, { useEffect } from 'react';

const ComponentExample = () => {
  useEffect(() => {
    console.log('Component mounted');
    // This runs once on mount
  }, []); // Empty array = runs only on mount
}

If you add a return function inside the useEffect() function, it is triggered when a component unmounts from the DOM.

import React, { useEffect } from 'react';

const ComponentExample = () => {
  useEffect(() => {
    console.log('Component mounted');
    
    // Return a cleanup function
    return () => {
      console.log('Component will unmount');
      // Cleanup: remove listeners, cancel subscriptions, etc.
    };
  }, []); // Empty array ensures cleanup runs only on unmount
}
↥ back to top

# 4.3. PURE COMPONENTS


Q. What are Pure Components in React?

Pure Components in React are the components which do not re-renders when the value of state and props has been updated with the same values. Pure Components restricts the re-rendering ensuring the higher performance of the Component.

Features of React Pure Components:

Example:

/**
 * React Pure Component
 */
export default class App extends React.PureComponent {
  constructor() {
    super();
    this.state = {
      userArray: [1, 2, 3, 4, 5]
    };
    // Here we are creating the new Array Object during setState using "Spread" Operator
    setInterval(() => {
      this.setState({
        userArray: [...this.state.userArray, 6]
      });
    }, 1000);
  }

  render() {
    return <b>Array Length is: {this.state.userArray.length}</b>;
  }
}

Try this example on CodeSandbox

↥ back to top

Q. What is difference between Pure Component vs Component?

PureComponent is exactly the same as Component except that it handles the shouldComponentUpdate() method. The major difference between React.PureComponent and React.Component is PureComponent does a shallow comparison on state change. It means that when comparing scalar values it compares their values, but when comparing objects it compares only references. It helps to improve the performance of the app.

A component rerenders every time its parent rerenders, regardless of whether the component's props and state have changed. On the other hand, a pure component will not rerender if its parent rerenders, unless the pure component's props (or state) have changed.

When to use React.PureComponent:

Example:

// Regular class component
class App extends React.Component {
  render() {
    console.log('Regular component rendered');
    return <h1>Component Example !</h1>
  }
}

// React Pure class component
class Message extends React.PureComponent {
  render() {
    console.log('Pure component rendered');
    return <h1>PureComponent Example !</h1>
  }
}
↥ back to top

Q. What are the problems of using render props with PureComponent?

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.

Example:

class Mouse extends React.PureComponent {
  // Mouse Component...
}

class MouseTracker extends React.Component {
  // Defined as an instance method, `this.renderTheCat` always
  // refers to *same* function when we use it in render
  renderTheCat(mouse) {
    return <Cat mouse={mouse} />;
  }

  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        {/* define the render function as instance method */}
        <Mouse render={this.renderTheCat} /> 
      </div>
    );
  }
}
↥ back to top

Q. When to use PureComponent over Component?

In React class components, use PureComponent over Component to optimize performance by preventing unnecessary re-renders. While Component re-renders every time its parent does, PureComponent only re-renders if its props or state actually change based on a shallow comparison.

When to Use PureComponent

When to Stick with Component

Example:

// ✅ Good use of PureComponent
class UserCard extends React.PureComponent {
  render() {
    const { name, age, email } = this.props; // Simple props
    return <div>{name} - {age} - {email}</div>;
  }
}

// ❌ Bad use of PureComponent
class UserProfile extends React.PureComponent {
  render() {
    const { user } = this.props; // Complex nested object
    return <div>{user.profile.settings.theme}</div>;
  }
}

Modern Alternative

React now recommends defining components as functions instead of classes. To get the performance benefits of PureComponent in a functional component, wrap it in React.memo().

↥ back to top

# 4.4. HIGHER ORDER COMPONENTS


Q. What are Higher Order Components in React.js?

Higher Order Components (HOCs) are advanced React patterns where a function takes a component and returns a new enhanced component with additional props or functionality.

Higher Order Components

Higher-Order Components are not part of the React API. They are the pattern that emerges from React's compositional nature. The component transforms props into UI, and a higher-order component converts a component into another component. The examples of HOCs are Redux's connect and Relay's createContainer.

/**
 * HOC that adds loading functionality
 */
function withLoading(Component) {
  return function WithLoadingComponent({ isLoading, ...props }) {
    if (isLoading) {
      return <div>Loading...</div>;
    }
    return <Component {...props} />;
  };
}

// Usage
const UserList = ({ users }) => (
  <ul>{users.map(user => <li key={user.id}>{user.name}</li>)}</ul>
);

const UserListWithLoading = withLoading(UserList);

// Render with loading state
<UserListWithLoading isLoading={true} users={[]} />

Note:

Modern alternatives:

HOCs are still valid, but Hooks are often preferred for most use cases:

// HOC approach
const UserProfile = withAuth(withData(Component));

// Hooks approach (cleaner)
function UserProfile() {
  const { isAuthenticated, user } = useAuth();
  const { data, loading } = useData('/api/user');
  
  if (!isAuthenticated) return <Redirect to="/login" />;
  if (loading) return <Spinner />;
  
  return <div>{data.name}</div>;
}

Try this example on CodeSandbox

↥ back to top

Q. What are the benefits of using HOC?

Benefits:

Problems:

↥ back to top

Q. What are Higher Order Component factory implementations?

Creating a higher order component basically involves manipulating WrappedComponent which can be done in two ways:

Both enable different ways of manipulating the WrappedComponent.

1. Props Proxy:

In this approach, The HOC creates a container component that wraps the WrappedComponent. It intercepts incoming props, adds or modifies them, and then passes them down.

Example:

function ppHOC(WrappedComponent) {
   return class PP extends React.Component {
     render() {
       return <WrappedComponent {...this.props}/>
     }
   }
}

Props Proxy can be implemented via a number of ways

2. Inheritance Inversion:

Inheritance Inversion allows the HOC to have access to the WrappedComponent instance via this keyword, which means it has access to the state, props, component lifecycle hooks and the render method.

Example:

function iiHOC(WrappedComponent) {
   return class Enhancer extends WrappedComponent {
     render() {
       return super.render()
     }
   }
}

Inheritance Inversion can be used in:

The key difference is that Props Proxy wraps the component from the outside, while Inheritance Inversion extends the component directly, giving deeper access to its internals.

Differences

Feature Props Proxy (PP) Inheritance Inversion (II)
Primary Method Composes via wrapping Composes via inheritance
Logic Type Adding/modifying props Manipulating render/state
Component Support Class & Functional Class only
Complexity Simple & Readable Advanced & Powerful
↥ back to top

Q. Explain Inheritance Inversion (iiHOC) in react?

Inheritance Inversion (iiHOC) is a powerful but rare implementation of Higher-Order Components where the returned component extends the WrappedComponent instead of wrapping it.

It is called “Inversion” because, in standard object-oriented programming, a specialized component would extend a base class to get more features. Here, the HOC (the enhancer) is the one doing the extending, giving it “passive” control over the original component.

Inheritance Inversion gives the HOC access to the WrappedComponent instance via this, which means we can use the state, props, component lifecycle and even the render method.

Example:

/**
 * Inheritance Inversion
 */
class Welcome extends React.Component {
  render() {
    return (
      <div> Welcome {his.props.user}</div>
    )
  }
}

const withUser = (WrappedComponent) => {
  return class extends React.Component {
    render() {
      if(this.props.user) {
        return  (
          <WrappedComponent {...this.props} />
        )
      }
      return <div>Welcome Guest!</div>
    }
  }
}

const withLoader = (WrappedComponent) => {
  return class extends WrappedComponent {
    render() {
      const { isLoader } = this.props
      if(!isLoaded) {
        return <div>Loading...</div>
      }
      return super.render()
    }
  }
}

export default withLoader(withUser(Welcome))
↥ back to top

Q. How to create props proxy for Higher Order Component component?

To create a props proxy for a Higher Order Component (HOC) in React, you wrap a component and pass all received props to the WrappedComponent. This allows the HOC to intercept, modify, or add props before passing them down.

Example:

function withPropsProxy(WrappedComponent) {
  return function PropsProxyComponent(props) {
    // You can modify or add props here if needed
    return <WrappedComponent {...props} />;
  };
}

Usage:

const EnhancedComponent = withPropsProxy(MyComponent);
// <EnhancedComponent someProp="value" /> will pass someProp to MyComponent

This pattern is called a “props proxy” because the HOC acts as a proxy for the props, allowing you to manipulate them as needed before rendering the wrapped component.

Props Proxy HOCs are useful to the following situations:

↥ back to top

Q. What is the purpose of displayName class property?

By default, React infers the displayName from the function or class name, but it can set it explicitly—especially useful for higher-order components (HOCs) that wrap other components, so the debug output reflects the wrapped component's name.

It helps tools like React DevTools and error messages show a clear, descriptive name for the component, making it easier to identify in the component tree.

Example:

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

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
↥ back to top

# 4.5. LAZY LOADING


Q. How to set up lazy loading components in React?

1. REACT.LAZY():

React.lazy is a function that lets you load components lazily through what is called code splitting without help from any external libraries. It makes possible for us to dynamically import components but they are rendered like regular components. This means that the bundle containing the component will only be loaded when the component is rendered.

React.lazy() takes a function that returns a promise as it's argument, the function returns a promise by calling import() to load the content. The returned Promise resolves to a module with a default containing the React Component.

Example: Create a lazy wrapper for your component

// Without Lazy
import MyComponent from './MyComponent';
 
// With Lazy
const MyComponent = React.lazy(() => import('./MyComponent'));

2. SUSPENSE:

React.Suspense is a component that can be used to wrap lazy components. A React.Suspense takes a fallback prop that can be any react element, it renders this prop as a placeholder to deliver a smooth experience and also give user feedback while the lazy component is being loaded.

Example: Use a suspense boundary with a custom loading indicator:

/**
 * Suspense
 */
import React, { Suspense } from 'react';

const MyComponent = React.lazy(() => import('./MyComponent'));

const App = () => {
  return (
    <div>
      <Suspense fallback={<div>Loading ... </div>}>
        <MyComponent />
      </Suspense>
    </div>
  );
}

Example: For navigation, lazy load each page and wrap the navigation area:

/**
 * React Lazy Loading Routes
 */
import { lazy, Suspense } from 'react';
import { Routes, Route, Link } from 'react-router-dom';

const Dashboard = lazy(() => import('./Dashboard'));
const Profile = lazy(() => import('./Profile'));

function Navigation() {
  return (
    <Suspense fallback={<span>Loading page...</span>}>
      <nav>
        <Link to="/">Dashboard</Link>
        <Link to="/profile">Profile</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Dashboard />} />
        <Route path="/profile" element={<Profile />} />
      </Routes>
    </Suspense>
  );
}

This method ensures components are loaded only when needed, improving performance and user experience.

Try this example on CodeSandbox

↥ back to top

# 5. REACT PROPS


Q. What is props in React?

In React, props (short for “properties”) are read-only objects used to pass data from a parent component to a child component. However, callback functions can also be passed, which can be executed inside the child to initiate an update.

Props are immutable so we cannot modify the props from inside the component. These attributes are available in the class component as this.props and can be used to render dynamic data in our render method.

Characteristics of Props

Example:

// Receiving Props
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Passing Props
const element = <Welcome name="Pradeep!" />;

Example: Destructuring

function Welcome({ name, age }) {
  return <h1>Hello, {name}. You are {age} years old.</h1>;
}

Special Props

Try this example on CodeSandbox

↥ back to top

Q. Why props in React are read only?

In React, props are read-only because components are designed to act like pure functions. This means they should not attempt to change their inputs (props) and must always return the same JSX output for the same set of props.

Here are the primary reasons why this rule is strictly enforced:

1. Unidirectional Data Flow

React follows a one-way data flow, where data travels from parent to child. If a child component could modify its own props, it would be effectively changing the state of its parent without the parent's knowledge. This would make the application's data flow unpredictable and extremely difficult to trace.

2. Predictability and Debugging

When props are immutable, you can be certain that a component's data won't change unexpectedly within its own scope. If a bug occurs, you only need to look “up” the component tree to the parent to find where the data originated, rather than checking every child that might have modified it.

3. Performance Optimization

React is highly efficient because it uses shallow reference equality to decide if a component needs to re-render.

4. Clear Separation of Concerns

A component should only be responsible for managing its own internal state. Props represent the “external interface” or the configuration provided by the outside world. Keeping them read-only ensures that components remain reusable and independent of where they are used.

Try this example on CodeSandbox

↥ back to top

Q. What are default props?

The defaultProps is a React component property that allows you to set default values for the props argument. If the prop property is passed, it will be changed.

The defaultProps can be defined as a property on the component class itself to set the default props for the class. defaultProps is used for undefined props, not for null props.

/**
 * Default Props
 */
class MessageComponent extends React.Component {
   render() {
        return (
          <div>Hello, {this.props.value}.</div>
        )
    }
}

// Pass default Props
MessageComponent.defaultProps = {
  value: 'World'  
}

For function components, you can use default values in destructuring:

Example:

function Greeting({ name = "Guest" }) {
  return <h1>Hello, {name}!</h1>;
}

Try this example on CodeSandbox

↥ back to top

Q. How to access props inside quotes in React JSX?

React JSX doesn't support variable interpolation inside an attribute value, but we can put any JS expression inside curly braces as the entire attribute value.

1. Concatenation

<img src={"images/" + this.props.image} />

2. Template literals

<img src={`images/${this.props.image}`} />

Example:

/**
 * Access Props
 */
class App extends Component {
  render() {
    return (
      <div>
        <img
          alt="React Logo"
  
          // Using ES6 template literals
          src={`${this.props.image}`} 
        />
      </div>
    );
  }
}
  
export default App;

Try this example on CodeSandbox

↥ back to top

Q. How to pass numbers to React component?

In react, numbers can be passed via curly braces({}) where as strings in quotes ("");

Example:

function App() {
  return <Greetings name="Pradeep" age={28} occupation="Software Developer" />;
}

// Greetings Component
function Greetings(props) {
  return (
    <h2>
      Hello! I'm {props.name}, a {props.age} years old {props.occupation}.
      Pleased to meet you!
    </h2>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How are boolean props used in React?

Boolean props in React are used to pass true/false values to components. In JSX:

Example:

/**
 * Boolean Props
 */
const MyComponent = ({ prop1, prop2 }) => (
  <div>
    <div>Prop1: {String(prop1)}</div>
    <div>Prop2: {String(prop2)}</div>
  </div>
) 

function App() {
  return (
    <div>
      <MyComponent prop1={true} prop2={false} />
      <MyComponent prop1 prop2 />
      <MyComponent prop1={false} prop2 />
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to apply validation on Props in React?

To apply validation on props in React, you can use either the PropTypes library for runtime checks or TypeScript for static type-checking during development

Example: Using PropTypes (Runtime Validation)

/**
 * Props Validation
 */
import PropTypes from 'prop-types';

function MyComponent({ name, age }) {
  return <h1>{name} is {age}</h1>;
}

MyComponent.propTypes = {
  name: PropTypes.string.isRequired, // Must be a string and is mandatory
  age: PropTypes.number  // Optional number
};

Example: Using TypeScript (Static Validation)

interface UserProps {
  name: string;
  age?: number; // The '?' makes it optional
}

const MyComponent: React.FC<UserProps> = ({ name, age }) => {
  return <h1>{name} is {age}</h1>;
};

Try this example on CodeSandbox

↥ back to top

Q. How to specify the shape of an object with PropTypes

The PropTypes.shape() validator can be used when describing an object whose keys are known ahead of time, and may represent different types.

Example:

/**
 * PropTypes.shape()
 * @param {*} props
 */
import PropTypes from "prop-types";

const Component = (props) => (
  <div>
    Component badge: {props.badge ? JSON.stringify(props.badge) : "none"}
  </div>
);

// PropTypes validation for the prop object
Component.propTypes = {
  badge: PropTypes.shape({
    src: PropTypes.string.isRequired,
    alt: PropTypes.string.isRequired
  })
};

const App = () => (
  <div>
    <Component badge= />
    {/*<Component badge=/>*/}
    <Component />
  </div>
);

export default App;

Output:

Component badge: {"src":"horse.png","alt":"Running Horse"}
Component badge: none

Try this example on CodeSandbox

↥ back to top

Q. How PropTypes.objectOf is different from PropTypes.shape?

PropTypes.shape checks for a specific structure (keys and their types) in an object. Each key can have a different type.

PropTypes.objectOf checks that all values in the object are of a specific type, but does not enforce specific keys.

Example:

PropTypes.shape({ name: PropTypes.string, age: PropTypes.number }) → Expects an object with keys name (string) and age (number).

PropTypes.objectOf(PropTypes.string) → Expects an object where all values are strings, regardless of the keys.

/**
 * PropTypes
 */
import PropTypes from 'prop-types';

// Expected prop object - dynamic keys (i.e. user ids)
const myProp = {
  25891102: 'Shila Jayashri',
  34712915: 'Employee',
  76912999: 'shila.jayashri@email.com'
};

// PropTypes validation for the prop object
MyComponent.propTypes = {
  myProp: PropTypes.objectOf(PropTypes.number)
};
↥ back to top

Q. How React PropTypes allow different types for one prop?

Using PropTypes.oneOfType() says that a prop can be one of any number of types. For instance, a phone number may either be passed to a component as a string or an integer:

/**
 * PropTypes.oneOfType()
 */
const Component = (props) => <div>Phone Number: {props.phoneNumber}</div>

Component.propTypes = {
  phoneNumber: PropTypes.oneOfType([
     PropTypes.number,
     PropTypes.string
  ]),
}

const App = () => (
  <div>
    <Component phoneNumber={04403472916}/>
    {/*<Component phoneNumber={"2823788557"}/>*/}
  </div>
);

Try this example on CodeSandbox

↥ back to top

Q. What are render props?

Render props are a React pattern where a component accepts a function as a prop, and calls that function to determine what to render.

The function receives data or state from the component and returns React elements. This enables sharing logic between components.

Example:

/**
 * Render Props
 */

import Wrapper from "./Wrapper";

class App extends React.Component {
  render() {
    return (
      <Wrapper
        render={({ increment, count }) => (
          <div>
            <h3>Render Props Counter</h3>
            <p>{count}</p>
            <button onClick={() => increment()}>Increment</button> 
          </div>
        )}
      />
    );
  }
}
/**
 * Wrapper Component
 */
class Wrapper extends React.Component {
  state = {
    count: 0
  };

  // Increase count
  increment = () => {
    const { count } = this.state;
    return this.setState({ count: count + 1 });
  };

  render() {
    const { count } = this.state;

    return (
      <div>
        {this.props.render({ increment: this.increment, count: count })}
      </div>
    );
  }
}

Important Caution: If you define a render prop function inline (inside the render method), it creates a new function on every render, which can cause performance issues by triggering unnecessary re-renders in child components.

Try this example on CodeSandbox

↥ back to top

Q. What are the benefits of using Render Props?

The benefits of using Render Props in React are:

Problems:

↥ back to top

Q. How do you create Higher Order Component using render props?

You can create a Higher Order Component (HOC) using render props by combining the two patterns: the HOC returns a component that uses a render prop to share logic or state with the wrapped component. Here is how you do it:

Example:

// HOC using render props
function withMouse(Component) {
  return class extends React.Component {
    render() {
      return (
        <Mouse
          render={mouse => <Component {...this.props} mouse={mouse} />}
        />
      );
    }
  };
}

// Render prop component
class Mouse extends React.Component {
  state = { x: 0, y: 0 };
  handleMouseMove = e => {
    this.setState({ x: e.clientX, y: e.clientY });
  };
  render() {
    return (
      <div style= onMouseMove={this.handleMouseMove}>
        {this.props.render(this.state)}
      </div>
    );
  }
}

// Usage
const Cat = ({ mouse }) => (
  <img src="cat.png" style= />
);

const CatWithMouse = withMouse(Cat);
↥ back to top

Q. Explain HOC vs render props in react.js?

1. Higher-Order Component (HOC):

Example:

function withLogger(WrappedComponent) {
  return function(props) {
    console.log('Props:', props);
    return <WrappedComponent {...props} />;
  };
}

2. Render Props:

Example:

<DataProvider render={data => <Display data={data} />} />

The render function receives data and returns React elements.

Key Differences:

↥ back to top

Q. What is children props?

The {this.props.children} is a special prop, automatically passed to every component, that can be used to render the content included between the opening and closing tags when invoking a component.

Example:

/**
 * React Children Props
 */
function MyComponent(props) {
  return <div>{props.children}</div>;
}

// Usage:
<MyComponent>
  <p>This is a child element.</p>
  <AnotherComponent />
</MyComponent>

Here, props.children will contain the <p> and <AnotherComponent /> elements.

Key points:

Try this example on CodeSandbox

↥ back to top

Q. When we should use React.cloneElement vs this.props.children?

1. React.cloneElement():

Use React.cloneElement() when you need to modify or add props to a child element before rendering it, such as injecting additional data, event handlers, or styling. This is useful for component composition where the parent wants to enhance or control its children.

2. this.props.Children():

Use this.props.children when you simply want to render the children passed to a component without modification. It's the default way to render nested elements in React.

Example: Using this.props.children

/**
 * React Children Props
 */
function Parent({ children }) {
  return <div>{children}</div>;
}

// Usage:
<Parent>
  <button>Click me</button>
</Parent>

The button is rendered as-is.

Example: Using React.cloneElement

/**
 * React Clone Element
 */
function Parent({ children }) {
  return React.cloneElement(children, { style: { color: 'red' } });
}

// Usage:
<Parent>
  <button>Click me</button>
</Parent>

The button is rendered with the additional style prop (text color red)

Summary:

Try this example on CodeSandbox

↥ back to top

Q. What do these three dots in React do?

In React, the three dots (…) are most commonly known as the Spread Operator. They are used to “spread” or expand the contents of an object or array into a new one.

1. Spread props: Pass all properties of an object as props to a component.

Example: This spreads all properties from the props object into the Profile component, so Profile receives name and age as props.

const props = { name: "Alice", age: 25 };

function Profile(props) {
  return <div>{props.name}, {props.age}</div>;
}

// Usage:
<Profile {...props} />

2. Merging Arrays or Objects: Create shallow copies or merge objects/arrays.

Example:

const [user, setUser] = useState({ name: "Alice", age: 25 });
const updates = { age: 26, city: "NY" };

setUser({ ...user, ...updates }); // Result: { name: "Alice", age: 26, city: "NY" }

3. Rest Parameters: In destructuring, ...rest gathers the remaining properties into a new object.

Example: Here, label is extracted from props, and all other props (type, className, etc.) are collected in rest and spread onto the <button> element.

function Button({ label, ...rest }) {
  return <button {...rest}>{label}</button>;
}

// Usage:
<Button label="Click Me" type="submit" className="primary" />

The spread operator is a JavaScript feature, not React-specific, but it's commonly used in React for props and state management.

↥ back to top

Q. Why we need to be careful when spreading props on DOM elements?

Spreading props directly onto DOM elements (e.g., <div {...props} />) is often considered an anti-pattern because it bypasses explicit control over what attributes are rendered to the browser.

To avoid these issues, always filter props and only pass valid attributes to DOM elements.

Example: By creating props specifically for DOM attribute, we can safely spread.

const Sample = () => (<Spread flag={true} domProps=/>);
const Spread = (props) => (<div {...props.domProps}>Test</div>);

Or alternatively we can use prop destructuring with ...rest:

const Sample = () => (<Spread flag={true} className="content"/>);
const Spread = ({ flag, ...domProps }) => (<div {...domProps}>Test</div>);

Note:

In scenarios where you use a PureComponent, when an update happens it re-renders the component even if domProps did not change. This is because PureComponent only shallowly compares the objects.

↥ back to top

Q. What will happen if you use props in initial state?

Using props to generate state in getInitialState often leads to duplication of “source of truth”, i.e. where the real data is. This is because getInitialState is only invoked when the component is first created.

The danger is that if the props on the component are changed without the component being ‘refreshed’, the new prop value will never be displayed because the constructor function (or getInitialState) will never update the current state of the component. The initialization of state from props only runs when the component is first created.

Bad:

The below component won't display the updated input value

class App extends React.Component {

  // constructor function (or getInitialState)
  constructor(props) {
    super(props)

    this.state = {
      records: [],
      inputValue: this.props.inputValue
    }
  }

  render() {
    return <div>{this.state.inputValue}</div>
  }
}

Good:

Using props inside render method will update the value:

class App extends React.Component {

  // constructor function (or getInitialState)
  constructor(props) {
    super(props)

    this.state = {
      records: []
    }
  }

  render() {
    return <div>{this.props.inputValue}</div>
  }
}
↥ back to top

Q. What is the difference between createElement and cloneElement?

React.createElement is used to create a new React element from scratch. It's what JSX compiles to under the hood. It is used when you want to define what to render for the first time.

React.cloneElement is used to clone and return a copy of an existing React element, with new props or children merged in. It's useful when you want to take an existing element (often passed as children) and add or override some props before rendering.

Example: React.createElement

import { createElement } from 'react';

function SimpleBanner() {
  // Equivalent to <h1 className="banner">Welcome!</h1>
  return createElement(
    'h1', 
    { className: 'banner' }, 
    'Welcome!'
  );
}

Example: React.cloneElement

import React, { Children, cloneElement } from 'react';

function RadioGroup({ name, children }) {
  return (
    <div className="radio-group">
      {/* 
        We map through children and "clone" each one, 
        merging the 'name' prop into them. 
      */}
      {Children.map(children, (child) => {
        if (React.isValidElement(child)) {
          return cloneElement(child, { name });
        }
        return child;
      })}
    </div>
  );
}

// Usage:
// Even though we did not add the 'name' prop to each <input />,
// RadioGroup will inject it into both clones.
function App() {
  return (
    <RadioGroup name="theme-selection">
      <input type="radio" value="light" /> Light
      <input type="radio" value="dark" /> Dark
    </RadioGroup>
  );
}

Note:

The React documentation warns that overusing cloneElement can make data flow harder to trace. In many cases, using render props or Context is preferred for passing data down the tree.

↥ back to top

Q. How to pass JSON Objects from Child to Parent Component?

To pass JSON objects (or any data) from a child to a parent component in React, you use a callback function. The parent defines a function and passes it as a prop to the child. The child calls this function, passing the JSON object as an argument.

Example:

/**
 * Parent Component
 */
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { dataFromChild: null };
    this.handleData = this.handleData.bind(this);
  }

  handleData(jsonObj) {
    this.setState({ dataFromChild: jsonObj });
  }

  render() {
    return (
      <div>
        <Child sendData={this.handleData} />
        <pre>{JSON.stringify(this.state.dataFromChild, null, 2)}</pre>
      </div>
    );
  }
}
/**
 * Child Component
 */
class Child extends React.Component {
  sendJsonToParent = () => {
    const jsonObj = { name: "Pradeep Kumar", age: 28 };
    this.props.sendData(jsonObj);
  };

  render() {
    return <button onClick={this.sendJsonToParent}>Send JSON to Parent</button>;
  }
}

Try this example on CodeSandbox

↥ back to top

Q. What is the use of this.props?

In React, the expression {...this.props} is called the “spread operator” for props. Its purpose is to pass all the props received by a component down to a child or DOM element, making it easier to forward or reuse props without listing each one individually.

Example:

<div {...this.props}>Content Here</div>

It is equal to Class Component

const person = {
    name: "Pradeep",
    age: 26,
    country: "India"
}

class SpreadExample extends React.Component {
    render() {
      const {name, age, country} = {...this.props}
      return (
        <div>
            <h3>Person Information:</h3>
            <ul>
              <li>name={name}</li>
              <li>age={age}</li>
              <li>country={country}</li>
            </ul>
        </div>
      )
    }
}
↥ back to top

# 6. REACT STATE


Q. What is State in React?

In React, state is a built-in object that stores data or information about the component. State allows a component to keep track of changing information between renders. When the state of a component changes, React automatically re-renders the component to reflect the new state.

Key Characteristics of State:

Example:

/**
 * React State
 */
import { useState } from 'react';

function Counter() {
  // Declares 'count' state variable and 'setCount' updater function
  const [count, setCount] = useState(0); 

  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Try this example on CodeSandbox

↥ back to top

Q. What does setState() do?

In React, the setState() method is used to update the state of a class component. When you call setState(), React schedules a re-render of the component with the new state values. This allows your UI to update in response to user actions or other events. setState() is asynchronous and can accept either an object with updated state values or a function that returns the new state based on the previous state.

Example:

/**
 * React setState()
 */
export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      color: "blue"
    };
  }

  handleColor = () => {
    this.setState({ color: "red" });
  };

  render() {
    return (
      <div>
        <h1>Color: {this.state.color}</h1>
        <button type="button" onClick={this.handleColor}>Change Color</button>
      </div>
    );
  }
}

Note:

In modern functional components, developers use the useState() Hook. While it serves the same purpose, there is a key difference: the “set” function from useState replaces the state instead of merging it

Try this example on CodeSandbox

↥ back to top

Q. Why is setState() in React async instead of sync?

In React, setState() is asynchronous instead of synchronous to optimize performance and ensure a smooth user experience. When you call setState(), React does not immediately update the state and re-render the component. Instead, it batches multiple state updates together and schedules a re-render for later, often after the current event loop finishes.

This batching helps avoid unnecessary renders and keeps the UI responsive, especially when many state updates happen in quick succession (like during user input or network events). If setState() were synchronous, each update would trigger an immediate re-render, which could make the app slow and unresponsive.

↥ back to top

Q. What is the second argument that can optionally be passed to setState() and what is its purpose?

The second argument to setState() in React Class Component is an optional callback function. Its purpose is to execute code after the state has been updated and the component has re-rendered. This is useful when you need to perform actions that depend on the updated state or the DOM being updated

Example:

/**
 * setState() Callback
 */
import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 }, () => {
      console.log('setState has finished and the component has re-rendered.');
      console.log('Updated count:', this.state.count);
    });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default Counter;

The setState() will always lead to a re-render unless shouldComponentUpdate() returns false. To avoid unnecessary renders, calling setState() only when the new state differs from the previous state makes sense and can avoid calling setState() in an infinite loop within certain lifecycle methods like componentDidUpdate().

↥ back to top

Q. What are the possible ways of updating objects in state?

Instead of directly modifying the state using this.state(), we use this.setState(). This is a function available to all React components that use state, and allows us to let React know that the component state has changed. This way the component knows it should re-render, because its state has changed and its UI will most likely also change.

Example:

1. Using Object.assign():

Create a copy of the object, update the property, and return the new object:

this.setState(prevState => {
  let user = Object.assign({}, prevState.user);  // creating copy of state variable user
  user.name = 'New Name';  // update the name property, assign a new value
  return { user };
})

2. Using spread Operator(...)

Spread the previous object and override the property you want to update:

this.setState(prevState => ({
    user: {                   
        ...prevState.user,    // keep all other key-value pairs
        name: 'New Name'       // update the value of specific key
    }
}))

3. For Nested Objects:

Spread each level to avoid mutation:

this.setState(prevState => ({
  user: {
    ...prevState.user,
    address: {
      ...prevState.user.address,
      city: 'New City'
    }
  }
}));

4. Functional Updates (with Hooks):

For functional components using useState():

setUser(prevUser => ({
  ...prevUser,
  name: 'New Name'
}));

Note:

Never mutate state directly. Always create a new object/array and update state with the new value. This ensures React can detect changes and re-render correctly.

Try this example on CodeSandbox

↥ back to top

Q. What will happen if you use setState() in constructor?

If you use setState() in the constructor of a React class component, it will not work as expected. The constructor is meant for direct state assignment using this.state = {...}. Calling setState() in the constructor does not update the state and does not trigger a re-render, because the component has not yet been mounted. React expects initial state to be set directly, not via setState(), inside the constructor.

Best practice:

Example:

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 }; // Correct way
    // Incorrect: setState() should NOT be used here
    this.setState({ count: 1 }); // This will be ignored!
  }

  render() {
    return <div>Count: {this.state.count}</div>;
  }
}

export default Counter;

Try this example on CodeSandbox

↥ back to top

Q. How to delete an item from state array?

To delete an item from a state array in React, you should never mutate the state directly. Instead, use the Array.prototype.filter() method to create a new array without the item you want to remove, and then update the state with this new array.

Example:

onDeleteByIndex(index) {
  this.setState({
    users: this.state.users.filter((item, i) => i !== index)
  });
}

Try this example on CodeSandbox

↥ back to top

Q. Why should not call setState() in componentWillUnmount()?

We should not call setState() in componentWillUnmount() because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again.

The componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. This method can be used to perform any necessary cleanup method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().

↥ back to top

Q. How can you re-render a component without using setState() function?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.

However, there may be cases where the render() method depends on some other data. After the initial mounting of components, a re-render will occur.

1. Using forceUpdate() (Class Component):

The following example generates a random number whenever it loads. Upon clicking the button, the forceUpdate() function is called which causes a new, random ​number to be rendered:

Example:

/**
 * forceUpdate()
 */
export default class App extends React.Component {
  constructor(){
    super();
    this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
  };
  
  forceUpdateHandler(){
    this.forceUpdate();
  };
  
  render(){
    return(
      <div>
        <button onClick= {this.forceUpdateHandler} >FORCE UPDATE</button>
        <h4>Random Number : { Math.random() }</h4>
      </div>
    );
  }
}

Caution: This method is discouraged because it bypasses shouldComponentUpdate and can lead to performance issues

2. Using useReducer() (Functional Components):

The most common way to “force” a re-render in functional components is to use a useReducer hook as a simple toggle or counter.

Example:

import { useReducer } from 'react';

function MyComponent() {
  // A simple counter that increments every time forceUpdate is called
  const [, forceUpdate] = useReducer((x) => x + 1, 0);

  const handleClick = () => {
    // This triggers a re-render without meaningful state data
    forceUpdate();
  };

  return <button onClick={handleClick}>Force Re-render</button>;
}

3. Changing the key Prop (Remounting):

By changing the key prop on a component, you force React to treat it as a brand-new element. This unmounts the old version and mounts a fresh instance, effectively resetting everything.

Example:

function Parent() {
  const [resetKey, setResetKey] = useState(0);

  return (
    <>
      <MyForm key={resetKey} />
      <button onClick={() => setResetKey(prev => prev + 1)}>Reset Form</button>
    </>
  );
}

4. Custom Hook with useState():

You can also create a reusable custom hook that uses a “dummy” state update to trigger a re-render

Example:

function useForceUpdate() {
  const [, setValue] = useState(0); 
  return () => setValue(value => value + 1); // update state to force render
}

Try this example on CodeSandbox

↥ back to top

Q. Why we need to pass a function to setState()?

The reason behind for this is that setState() is an asynchronous operation. React batches state changes for performance reasons, so the state may not change immediately after setState() is called. That means we should not rely on the current state when calling setState().

The solution is to pass a function to setState(), with the previous state as an argument. By doing this we can avoid issues with the user getting the old state value on access due to the asynchronous nature of setState().

Problem:

// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3

Try this example on CodeSandbox

Solution:

this.setState((prevState) => ({
  count: prevState.count + 1
}));
this.setState((prevState) => ({
  count: prevState.count + 1
}));
this.setState((prevState) => ({
  count: prevState.count + 1
}));
// this.state.count === 3 as expected

Try this example on CodeSandbox

↥ back to top

Q. How to update nested state properties in React.js?

To update nested state properties in React.js, you should create a new copy of the nested object or array you want to update, modify it, and then set the new state. This ensures immutability, which is important for React to detect changes and re-render correctly.

Example:

const [user, setUser] = useState({
  name: "Pradeep",
  address: {
    city: "Ranchi",
    zip: "560076"
  }
});

To update the city:

setUser(prevUser => ({
  ...prevUser,
  address: {
    ...prevUser.address,
    city: "Bengaluru"
  }
}));

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between state and props?

Props are read-only, immutable data passed from parent to child components. They allow components to receive data and functions from their parent, enabling reusability and unidirectional data flow. Props cannot be changed by the receiving component.

State is mutable data managed within a component. It represents information that can change over time, usually in response to user actions. State is local to the component and can be updated using setState (class) or useState (function), causing the component to re-render.

Props State
Props are read-only. State changes can be asynchronous.
Props are immutable. State is mutable.
Props allow you to pass data from one component to other components as an argument. State holds information about the components.
Props can be accessed by the child component. State cannot be accessed by child components.
Props are used to communicate between components. States can be used for rendering dynamic changes with the component.
Stateless component can have Props. Stateless components cannot have State.
Props make components reusable. State cannot make components reusable.
Props are external and controlled by whatever renders the component. The State is internal and controlled by the React Component itself.
↥ back to top

Q. How to set state with a dynamic key name?

To set a state with a dynamic key name in React, use ES6 computed property names by wrapping the variable or expression in square brackets [] within your state update.

1. Using the useState() Hook:

When using objects in functional components, you must spread the previous state to avoid overwriting other keys

Example:

const [formData, setFormData] = useState({ firstName: '', lastName: '' });

const handleChange = (e) => {
  const { name, value } = e.target;
  
  // Use [name] to dynamically target the correct key
  setFormData(prevState => ({
    ...prevState,
    [name]: value
  }));
};

2. Using Class Components (setState):

In class components, React automatically merges top-level state, so you don't always need to spread the previous state unless you are updating nested objects.

Example:

handleChange(event) {
  const { name, value } = event.target;
  
  // Square brackets evaluate the 'name' variable as the key
  this.setState({
    [name]: value
  });
}

Try this example on CodeSandbox

↥ back to top

Q. How to listen state change in React.js?

In class components, use the componentDidUpdate(prevProps, prevState) lifecycle method. It runs after every update, so you can compare prevState with the current state to detect changes.

Example:

componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    console.log('Count changed:', this.state.count);
  }
}

In functional components, use the useEffect() hook with the state variable as a dependency. The effect runs whenever that state changes.

Example:

export function MyComponent(props) {
  const [count, setCount] = useState(0);

  useEffect(() => {
      console.log('Count changed:', count)
  },[count]) // <-- here put the parameter to listen
}
↥ back to top

Q. How to access child's state in React?

In React, you can access a child component's state from the parent using refs. This is mainly possible with class components. The parent creates a ref and attaches it to the child. The parent can then call methods on the child to get or update its state.

Example:

// Parent Component
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.childRef = React.createRef();
  }
  handleClick = () => {
    // Access child method or state
    const childInstance = this.childRef.current;
    alert(childInstance.state.value); // or call a method
  };
  render() {
    return (
      <>
        <Child ref={this.childRef} />
        <button onClick={this.handleClick}>Get Child State</button>
      </>
    );
  }
}

// Child Component
class Child extends React.Component {
  state = { value: "Hello from Child" };
  render() {
    return <div>{this.state.value}</div>;
  }
}

Note:

This approach is not recommended for most cases. Prefer passing data up via callbacks. Use refs only when necessary.

Try this example on CodeSandbox

↥ back to top

Q. How to change the state of a child component from its parent in React?

To change the state of a child component from its parent in React, you should follow the “lifting state up” pattern:

/**
 * Change Child state from its Parent
 * @param {*} param0
 */
const Child = ({ open }) => {
  return <h2>Child State: {open.toString()}</h2>;
};

const Parent = () => {
  const [isOpen, setIsOpen] = React.useState(false);

  const toggleChild = () => {
    setIsOpen((prevValue) => !prevValue);
  };

  return (
    <div>
      <button onClick={toggleChild}>Click Me</button>
      {/* Pass a callback to Child */}
      <Child open={isOpen} />
    </div>
  );
};

export default Parent;

Try this example on CodeSandbox

↥ back to top

Q. How does the state differ from props in React?

1. State:

This is data maintained inside a component. It is local or owned by that specific component. The component itself will update the state using the setState() function.

Example:

class AppComponent extends React.component {
  state = {
      msg : 'Hello World!'
  }

  render() {
      return <div>Message {this.state.msg}</div>
  }
}

2. Props:

Data passed in from a parent component. props are read-only in the child component that receives them. However, callback functions can also be passed, which can be executed inside the child to initiate an update.

Example: The parent can pass a props by using this

<ChildComponent color='red' />

Inside the ChildComponent constructor we could access the props

class ChildComponent extends React.Component {
  constructor(props) {
    super(props)
    console.log(props.color)
  }
}

Props can be used to set the internal state based on a prop value in the constructor, like this

class ChildComponent extends React.Component {
  constructor(props) {
    super(props)
    this.state.colorName = props.color
  }
}

Props should never be changed in a child component. Props are also used to allow child components to access methods defined in the parent component. This is a good way to centralize managing the state in the parent component, and avoid children to have the need to have their own state.

Difference between State and Props:

Props State
Props are read-only. State changes can be asynchronous.
Props allow to pass data from one component to other components as an argument. State holds information about the components.
Props can be accessed by the child component. State cannot be accessed by child components.
Props are used to communicate between components. States can be used for rendering dynamic changes with the component.
Stateless component can have Props. Stateless components cannot have State.
Props are external and controlled by whatever renders the component. The State is internal and controlled by the React Component itself.
↥ back to top

# 7. REACT EVENTS


Q. What is meant by event handling in React?

Event handling in React means responding to user actions like clicks, typing, form submits, mouse movement, etc., by attaching handler functions to JSX elements.

Core Concepts:

Example:

/**
 * Event Handling
 */
function Button() {
  const handleClick = () => {
    console.log("Button clicked");
  };

  return <button onClick={handleClick}>Click Me</button>;
}

Try this example on CodeSandbox

↥ back to top

Q. What are the common event handlers in React?

React provides a wide range of built-in event handlers that follow standard HTML events but use camelCase naming conventions. Below are the most common event handlers categorized by their interaction type:

1. Mouse Events

2. Form & Input Events

3. Keyboard Events

4. Other Common Events

↥ back to top

Q. How to pass a parameter to event handlers in React?

Example:

const message = "Hello World!";

export default function App() {
  const displayMessage = (message) => {
    alert(message);
  };

  return (
    <button onClick={() => displayMessage(message)}>CLICK ME</button>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How do you pass an event handler to a component?

In React, you pass an event handler to a component by defining a function in the parent and passing it as a prop to the child component. The child then “plugs” that prop into a standard HTML event attribute like onClick.

Pattern:

Example:

/**
 * Pass an event handler to a component
 */
import { useState } from "react";

// Child receives handler via props and wires it to a DOM event
const CustomButton = ({ onCustomClick }: { onCustomClick: () => void }) => {
  return <button onClick={onCustomClick}>Increment</button>;
};

// Parent defines the handler and passes it down
const Container = () => {
  const [counter, setCounter] = useState(0);

  const handleCustomClick = () => {
    setCounter(counter + 1);
  };

  return (
    <div>
      <p>Count: {counter}</p>
      <CustomButton onCustomClick={handleCustomClick} />
    </div>
  );
};

export default Container;

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between HTML and React event handling?

In HTML, the attribute name is in all lowercase and is given a string invoking a function defined somewhere:

<!-- HTML -->
<button onclick="handleClick()">Click</button>

In React, the attribute name is camelCase and are passed the function reference inside curly braces:

// React
<button onClick={handleClick}>Click</button>

In HTML, false can be returned to prevent default behavior, whereas in React preventDefault() has to be called explicitly.

<a href="#" onclick="console.log('The link was clicked.'); return false" />

function handleClick(e) {
  e.preventDefault()
  console.log("The link was clicked.")
}
↥ back to top

Q. How to bind methods or event handlers in JSX callbacks?

There are 3 possible ways to achieve this

1. Event Handler in Render Method:

We can bind the handler when it is called in the render method using bind() method.

handleClick() {
  // ...       
}

<button onClick={this.handleClick.bind(this)}>Click</button> 

Try this example on CodeSandbox

2. Event Handler using Arrow Function:

In this approach we are binding the event handler implicitly. This approach is the best if you want to pass parameters to your event.

handleClick() {
  // ...       
}

<button onClick={() => this.handleClick()}>Click</button> 

Try this example on CodeSandbox

3. Event Handler in Constructor:

This has performance benefits as the events aren't binding every time the method is called, as opposed to the previous two approaches.

constructor(props) {

  // This binding is necessary to make `this` work in the callback
  this.handleClick = this.handleClick.bind(this);
}

handleClick() {
  // ...       
}

<button onClick={this.handleClick}>Click</button>

Try this example on CodeSandbox

↥ back to top

Q. Why do we need to bind methods inside class component constructor?

In Class Components, when we pass the event handler function reference as a callback like this

<button type="button" onClick={this.handleClick}>Click Me</button>

the event handler method loses its implicitly bound context. When the event occurs and the handler is invoked, the this value falls back to default binding and is set to undefined, as class declarations and prototype methods run in strict mode.

When we bind the this of the event handler to the component instance in the constructor, we can pass it as a callback without worrying about it losing its context.

Arrow functions are exempt from this behavior because they use lexical this binding which automatically binds them to the scope they are defined in.

Example:

/**
 * Event Handling in React
 */
import React from "react";

export default class App extends React.Component {
  constructor(props: object) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    alert("Click event triggered!");
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

Try this example on CodeSandbox

↥ back to top

Q. How do I pass a parameter to an event handler or callback?

You can use an arrow function to wrap around an event handler and pass parameters:

1. Arrow function (most common):

<button onClick={() => handleClick(id)}>Click</button>

2. bind version (equivalent):

This is equivalent to calling .bind

<button onClick={handleClick.bind(null, id)}>Click</button>

// using event object
<button onClick={(e) => handleClick(id, e)}>Click</button>

Example:

/**
 * Pass parameter to an event handler
 */
import { useState } from 'react';

const A = 65; // ASCII character code

const App = () => {
  const [justClicked, setJustClicked] = useState<string | null>(null);
  const [letters] = useState(Array.from({ length: 26 }, (_, i) => String.fromCodePoint(A + i)));

  const handleClick = (letter: string) => {
    setJustClicked(letter);
  };

  return (
    <>
      Just clicked: {justClicked}
      <ul>
        {letters.map((letter) => (
          <li key={letter}>
            <button type="button" onClick={() => handleClick(letter)}>
              {letter}
            </button>
          </li>
        ))}
      </ul>
    </>
  );
};

export default App;

Try this example on CodeSandbox

↥ back to top

Q. When should we use arrow functions with React?

In modern React, arrow functions are the standard for most use cases due to their concise syntax and lexical this binding, which simplifies handling state and props

When to Use Arrow Functions

Example:

import React from 'react'

class Button extends React.Component {
  render() {
    return (
      <button onClick={this.handleClick} style={this.state}>
        Set background to red
      </button>
    )
  }

  handleClick = () => {
    this.setState({ backgroundColor: 'red' })
  }
}
  1. When we use this it generates a new function on every render, which will obviously have a new reference.
  2. If the component we pass this generated function to is extending PureComponent(), it will not be able to bail out on rerendering, even if the actual data has not changed.
↥ back to top

Q. Is it good to use arrow functions in render methods?

Problem:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. When arrow functions and binds in render. It breaks performance optimizations like shouldComponentUpdate() and PureComponent.

Example:

class App extends React.Component {
  constructor(props) {
    super(props);
    ...
  }

  deleteUser = id => {
    this.setState(prevState => {
      return {
        users: prevState.users.filter(user => user.id !== id)
      };
    });
  };

  render() {
    return (
      <div>
        <ul>
          {this.state.users.map(user => {
            return (
              <User key={user.id} name={user.name} id={user.id}
                onDeleteClick={() => this.deleteUser(user.id)}
              />
            );
          })}
        </ul>
      </div>
    );
  }
}

Try this example on CodeSandbox

Solution:

In below example, App Component has no arrow function in render. Instead, the relevant data is passed down to User Component. In User Component, onDeleteClick() calls the onClick function passed in on props with the relevant user.id.

// User Component
class User extends React.PureComponent {
  onDeleteClick = () => {
    // No bind needed since we can compose the relevant data for this item here
    this.props.onClick(this.props.user.id);
  };

  render() {
    console.log(`${this.props.user.name} just rendered`);
    return (
      <li>
        <input type="button" value="Delete" onClick={this.onDeleteClick} />
        {this.props.user.name}
      </li>
    );
  }
}
// App Component
class App extends React.Component {
  constructor(props) {
    super(props);
    ...
  }

  deleteUser = id => {
    this.setState(prevState => {
      return { 
        users: prevState.users.filter(user => user.id !== id) 
      };
    });
  };

  renderUser = user => {
    return <User key={user.id} user={user} onClick={this.deleteUser} />;
  }

  render() {
    return (
      <div>
        <ul>
          {this.state.users.map(this.renderUser)}
        </ul>
      </div>
    );
  }
}

Try this example on CodeSandbox

↥ back to top

Q. How to avoid the need for binding in React?

1. Use Arrow Function in Class Property:

Arrow methods capture lexical this, so they are auto-bound.

import React from 'react';

class Button extends React.Component {
  state = { clicked: false };

  handleClick = () => {
    this.setState({ clicked: true });
  };

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

export default Button;

2. Bind in Render:

onChange={this.handleChange.bind(this)}

This approach is terse and clear, however, there are performance implications since the function is reallocated on every render.

3. Bind in Constructor:

One way to avoid binding in render is to bind in the constructor

constructor(props) {
  super(props)
  this.handleChange = this.handleChange.bind(this)
}

This is the approach currently recommended in the React docs for “better performance in your application”.

4. Function components with hooks (modern React):

import React from 'react';

function Button() {
  const [clicked, setClicked] = React.useState(false);
  const handleClick = () => setClicked(true);

  return <button onClick={handleClick}>{clicked ? "Clicked!" : "Click"}</button>;
}

export default Button;
↥ back to top

Q. How do I bind a function to a component instance?

There are several ways to make sure functions have access to component attributes like this.props and this.state, depending on which syntax and build steps you are using.

1. Bind in Constructor (ES5):

import { Component } from 'react';

class App extends Component {
  constructor(props: object) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    console.log('Clicked!');
  }
  render() {
    return <button onClick={this.handleClick}>Click Me</button>
  }
}

export default App;

2. Class Properties:

import { Component } from 'react';

class App extends Component {

  handleClick = () => {
    console.log('Clicked!');
  }
  render() {
    return <button onClick={this.handleClick}>Click Me</button>
  }
}

export default App;

3. Bind in Render:

import { Component } from 'react';

class App extends Component {
  handleClick() {
    console.log('Click happened')
  }
  render() {
    return <button onClick={this.handleClick.bind(this)}>Click Me</button>
  }
}

export default App;

Note:

Using Function.prototype.bind in render creates a new function each time the component renders, which may have performance implications

4. Arrow Function in Render:

import { Component } from 'react';

class App extends Component {
  handleClick() {
    console.log('Click happened')
  }
  render() {
    return <button onClick={() => this.handleClick()}>Click Me</button>
  }
}

export default App;

Note:

Using an arrow function in render creates a new function each time the component renders, which may break optimizations based on strict identity comparison.

Best Practice:

↥ back to top

Q. How can I prevent a function from being called too quickly?

1. Throttle:

Throttling prevents a function from being called more than once in a given window of time. It runs at most once every N ms. Good for scroll, resize, mousemove.

Example:

import { throttle } from "lodash";

const onScroll = throttle(() => {
  console.log("run at most every 200ms");
}, 200);

2. Debounce:

Debouncing ensures that a function will not be executed until after a certain amount of time has passed since it was last called. This can be useful when you have to perform some expensive calculation in response to an event that might dispatch rapidly (eg scroll or keyboard events).

It waits until calls stop for N ms, then runs once. Good for search input, autosave.

Example:

import { debounce } from "lodash";

const onSearchChange = debounce((value) => {
  console.log("run after user stops typing");
}, 300);

Example:

/**
 * Throttle and Debounce in React
 */
import * as React from "react";
import * as _ from "lodash";

export default class App extends React.Component<object, { count: number }> {
  state = { count: 0 };

  handleCount() {
    this.setState((state) => ({
      count: state.count + 1
    }));
  }

  // You will run count() only once after 100ms
  handleDebounce = _.debounce(() => this.handleCount(), 100);

  // You will run count() every 200ms
  handleThrottle = _.throttle(() => this.handleCount(), 200);

  render() {
    return (
      <div>
        {this.state.count}
        <hr />
        <button onClick={this.handleThrottle}>Click Me - Throttle </button>
        <button onClick={this.handleDebounce}>Click Me - Debounce </button>
      </div>
    );
  }
}

Try this example on CodeSandbox

3. RequestAnimationFrame Throttling:

RequestAnimationFrame (rAF) Throttling is a performance optimization technique that limits the execution of a function to match the browser's native repaint cycle (typically 60 times per second, or every 16.67ms).

/**
 * RequestAnimationFrame Throttling
 */
/**
 * RequestAnimationFrame Throttling
 */
import React from "react";
import rafSchedule from "raf-schd";

type Point = { x: number; y: number };
type Props = { onScroll: (point: Point) => void };

export default class App extends React.Component<Props> {
  scheduleUpdate = rafSchedule((point: Point) => this.props.onScroll(point));

  constructor(props: Props) {
    super(props);
    this.handleScroll = this.handleScroll.bind(this);
  }

  handleScroll(e: React.UIEvent<HTMLDivElement> & { clientX: number; clientY: number }) {
    // When we receive a scroll event, schedule an update.
    // If we receive many updates within a frame, we'll only publish the latest value.
    this.scheduleUpdate({ x: e.clientX, y: e.clientY });
  }

  componentWillUnmount() {
    // Cancel any pending updates since we're unmounting.
    this.scheduleUpdate.cancel();
  }

  render() {
    return (
      <div style= onScroll={this.handleScroll}>
        <img src="https://picsum.photos/800/600" alt="Nature" />
      </div>
    );
  }
}

Try this example on CodeSandbox

↥ back to top

Q. Explain synthetic event in React.js?

A Synthetic Event in React is a cross-browser wrapper around the browser's native event system. It provides a consistent interface that ensures events behave identically across different browsers, such as Chrome, Firefox, and Safari, by normalizing their properties

Key Features:

Example:

function Button() {
  const handleClick = (e) => {
    e.preventDefault();
    console.log(e.type);        // "click" (Synthetic Event)
    console.log(e.nativeEvent); // underlying DOM event
  };

  return <button onClick={handleClick}>Click</button>;
}

SyntheticEvent Object:

React SyntheticEvent gives a normalized event object with these common methods/properties:

void preventDefault()
void stopPropagation()
boolean isPropagationStopped()
boolean isDefaultPrevented()
boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
DOMEventTarget target
number timeStamp
string type
↥ back to top

Q. How to trigger click event programmatically?

To trigger a click event programmatically in React, you typically use a ref to access the underlying DOM element and then call its native .click() method

Example:

import { useRef } from 'react';

function MyComponent() {
  const buttonRef = useRef(null);

  const triggerClick = () => {
    // Check if the ref is attached, then trigger the click
      buttonRef.current?.click();
  };

  return (
    <>
      {/* Target element */}
      <button ref={buttonRef} onClick={() => console.log("Real button clicked")}>Target Button</button>
      <button onClick={triggerClick}>Trigger Programmatically</button>
    </>
  );
}
↥ back to top

Q. How to listen for click events that are outside of a component?

To listen for click events outside a React component, the standard approach is to attach a click listener to the document and use a Ref to check if the clicked element is contained within your component.

Using Custom Hook:

Example:

import { useEffect, useRef } from "react";

function OutsideClickBox({ onOutsideClick, children }) {
  const boxRef = useRef(null);

  useEffect(() => {
    function handlePointerDown(event) {
      if (!boxRef.current) return;
      if (!boxRef.current.contains(event.target)) {
        onOutsideClick?.(event);
      }
    }

    document.addEventListener("mousedown", handlePointerDown);

    return () => {
      document.removeEventListener("mousedown", handlePointerDown);
    };
  }, [onOutsideClick]);

  return <div ref={boxRef}>{children}</div>;
}

How it works:

Note:

Use mousedown instead of click if you want the outside action to happen earlier (before focus/click side effects inside other elements).

Try this example on CodeSandbox

↥ back to top

Q. How to convert text to uppercase on user input entered?

To convert text to uppercase as a user types, you should update the state using .toUpperCase() within the onChange handler. This keeps your React state and the input field in sync.

Example:

import { useState } from "react";

export default function App() {
  const [text, setText] = useState("");

  const handleChange = (e) => {
    // Convert the input value to uppercase before saving to state
    setText(e.target.value.toUpperCase());
  };

  return (
    <input
      type="text"
      value={text}
      onChange={handleChange}
      placeholder="TYPE SOMETHING..."
    />
  );
}
↥ back to top

Q. What are the pointer events in React?

In React, pointer events are a set of Synthetic Events designed to provide a unified way to handle inputs from various pointing devices, including mice, touchscreens, and pens/styluses. Instead of writing separate logic for mouse and touch interactions, you can use these events to cover all input types with a single handler.

Common pointer event handlers are:

Example:

function Box() {
  const handlePointerDown = (e) => {
    console.log("Started with:", e.pointerType); // mouse | touch | pen
  };

  return (
    <div
      onPointerDown={handlePointerDown}
      onPointerMove={(e) => console.log(e.clientX, e.clientY)}
      onPointerUp={() => console.log("Pointer up")}
      style=
    >
      Interact here
    </div>
  );
}
↥ back to top

Q. What is an alternative way to avoid having to bind to this in event callback methods?

1. Bind in Constructor:

class App extends Component {

  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    console.log('Clicked !')
  }
  render() {
    return <button onClick={this.handleClick}>Click Me</button>
  }
}

2. Bind in Render:

class App extends Component {

  handleClick() {
    console.log('Clicked !')
  }
  render() {
    return <button onClick={this.handleClick.bind(this)}>Click Me</button>
  }
}

3. Arrow Function in Render:

class App extends Component {

  handleClick() {
    console.log('Clicked !')
  }
  render() {
    return <button onClick={() => this.handleClick()}>Click Me</button>
  }
}

Note:

Using an arrow function in render creates a new function each time the component renders, which may break optimizations based on strict identity comparison.

↥ back to top

Q. What is the alternative of binding this in the constructor?

Arrow Function creates and binds the function all at once. Inside render (and elsewhere), the function is already bound because the arrow function preserves the this binding.

Example:

class Button extends React.Component {
  // no binding
  handleClick = (e) => {
    console.log('clicked !');
  }
  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}
↥ back to top

# 8. REACT LISTS


Q. Explain the Lists in React?

In React, Lists refer to the practice of rendering multiple similar components or elements from a collection of data, such as an array. Lists are rendered by transforming an array of data into JSX elements, usually with .map().

Example:

/**
 * React List
 */
const items = ['Apple', 'Banana', 'Cherry'];

function FruitList() {
  return (
    <ul>
      {items.map((item) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}

The “Key” Prop:

Try this example on CodeSandbox

↥ back to top

Q. Why do I need Keys in React Lists?

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:

Example:

const numbers = [10, 20, 30, 40, 50];

const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

React recommends that you do not use indexes as keys, if the order of items may change. It could impact performance negatively and could lead to some unstable component behavior.

↥ back to top

Q. How to display an array of strings in react component?

To display an array of strings in a React component, the most common and recommended approach is to use the .map() method. This method iterates through the array and returns a new array of JSX elements that React can render.

Example:

function MyList() {
  
  const items = ["this is line #1", "this is line #2", "this is line #3"];

  return (
    <ul>
      {items.map((item) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}
export default MyList;

Try this example on CodeSandbox

↥ back to top

Q. How do you render Array, Strings and Numbers in React?

/**
 * Array Component
 */
const frameworks = [
  { id: 1, name: "Angular"},
  { id: 2, name: "React"},
  { id: 3, name: "Vue.js"}
];

const ArrayList = (props) => (
  <div>
    <h2>Array of Objects</h2>
    <ul>
    {frameworks.map((item, index) => (
      <li key={item.id}>{item.name}</li>
    ))}
    </ul>
  </div>
);


/**
 * String Component
 */
const words = ["hello", "react", "world"];

const StringList = (props) => (
  <h3>Array of Strings</h3>
  <ul>
    {words.map((word, index) => (
      <li key={index}>{word}</li>
    ))}
  </ul>
);


/**
 * Number Component
 */
const numbers = [10, 20, 30];

const NumberList = (props) => (
  <h3>Array of Numbers</h3>
  <ul>
    {numbers.map((num) => (
      <li key={num}>{num}</li>
    ))}
  </ul>
);

Try this example on CodeSandbox

↥ back to top

Q. How do keys help React reconciliation?

When React re-renders a list, it needs to figure out which items changed, were added, or were removed. Without keys, React compares elements by their position in the array. With keys, React compares elements by their stable identity, which is far more efficient and correct.

React's diffing algorithm (reconciliation) works in two phases:

  1. Without keys (index-based diffing): React assumes the element at position 0 is the same element as before, position 1 is the same, and so on. If you prepend an item to a list of 100 items, React sees every single element as “changed” and re-renders all 100.

  2. With keys (identity-based diffing): React uses the key to match old elements to new ones. If you prepend an item, React recognizes that the existing 100 elements are unchanged (same keys), creates only the new one, and leaves the rest untouched.

Example — why position-based diffing breaks:

// Initial render
<ul>
  <li key={0}>Alice</li>   {/* index 0 */}
  <li key={1}>Bob</li>     {/* index 1 */}
</ul>

// After prepending "Zara" — React sees EVERY element as "changed"
<ul>
  <li key={0}>Zara</li>   {/* index 0  React thinks Alice became Zara */}
  <li key={1}>Alice</li>  {/* index 1  React thinks Bob became Alice */}
  <li key={2}>Bob</li>    {/* index 2  React thinks this is a new element */}
</ul>

Example — stable keys fix this:

const users = [
  { id: 'u3', name: 'Zara' },
  { id: 'u1', name: 'Alice' },
  { id: 'u2', name: 'Bob' },
];

// React matches by ID, not position — Alice and Bob are untouched
<ul>
  {users.map(user => (
    <li key={user.id}>{user.name}</li>
  ))}
</ul>

What makes a good key:

Good ✅ Bad ❌
Stable unique ID from data (user.id) Array index when list can reorder
UUID or database primary key Math.random() (new key every render)
Slug or unique string identifier Index when items can be inserted/deleted

Key rules:

Try this example on CodeSandbox

↥ back to top

Q. Can a child component access the key prop directly?

No. key is a reserved prop in React. React consumes it internally for reconciliation and does not pass it down to the component as part of props. If you try to read props.key inside a child, you will always get undefined.

Example: key is NOT accessible via props:

function ListItem({ id, name }) {
  // ✅ 'id' and 'name' are accessible
  // ❌ 'key' is NOT — it is stripped by React before props reach the component
  return <li>{name}</li>;
}

function List() {
  const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
  ];

  return (
    <ul>
      {users.map(user => (
        <ListItem key={user.id} id={user.id} name={user.name} />
      ))}
    </ul>
  );
}

Workaround — pass the ID as a separate prop:

If the child needs the identifier value (e.g., to make an API call or handle a delete), pass it explicitly as a separate prop alongside key:

// Pass id separately so the child can use it
<ListItem key={user.id} id={user.id} name={user.name} />

Inside ListItem, props.id will work correctly, while props.key will always be undefined.

Why does React do this?

key is part of React's internal reconciliation mechanism, not application data. Exposing it as a prop would conflate two separate concerns — component identity (React's job) and component data. Keeping them separate makes the API cleaner and avoids accidental misuse.

↥ back to top

Q. How do you avoid re-rendering the whole list unnecessarily?

When a parent re-renders, every child in a .map() list re-renders too — even if their individual data didn't change. There are several techniques to prevent this.

1. Use stable keys (prerequisite):

Always use stable, unique IDs as keys. This lets React skip DOM mutations for unchanged items during reconciliation.

{users.map(user => <UserCard key={user.id} user={user} />)}

2. Wrap list items with React.memo:

React.memo is a higher-order component that skips re-rendering if props are shallowly equal. Wrap the individual list-item component, not the list itself.

const UserCard = React.memo(function UserCard({ user }) {
  console.log('rendered:', user.name);
  return <li>{user.name}</li>;
});

Now only the UserCard whose user prop actually changed will re-render.

3. Stabilize callback props with useCallback:

If you pass a callback (e.g., onDelete) to each list item, a new function reference is created on every parent render — breaking React.memo shallow comparison. Wrap callbacks in useCallback to keep the reference stable.

const handleDelete = useCallback((id) => {
  setUsers(prev => prev.filter(u => u.id !== id));
}, []); // stable reference — React.memo on child now works correctly

{users.map(user => (
  <UserCard key={user.id} user={user} onDelete={handleDelete} />
))}

4. Avoid creating new object/array references in render:

Inline object or array literals inside JSX always produce a new reference, defeating React.memo.

// ❌ Bad — new object on every render
<UserCard key={user.id} style= user={user} />

// ✅ Good — stable reference defined outside render
const cardStyle = { color: 'red' };
<UserCard key={user.id} style={cardStyle} user={user} />

5. Keep state as flat and granular as possible:

If a single item changes and the whole list array reference changes, all memoized children will re-render if they receive the full item object. Prefer normalized state (e.g., a map of id → item) so mutations only touch the relevant slice.

// ❌ Array — updating one item rebuilds the whole array
const [users, setUsers] = useState([...]);

// ✅ Map — updating one entry does not disturb others
const [usersById, setUsersById] = useState({ u1: {...}, u2: {...} });
↥ back to top

Q. How do you sort a list in React without mutating state?

The key rule is: never call .sort() directly on the state array, because Array.prototype.sort() sorts in place and mutates the original array. Instead, create a shallow copy first using the spread operator ([...arr]) or .slice(), then sort the copy.

Why mutation is dangerous in React:

React uses reference equality to detect state changes. If you mutate the existing array, the reference stays the same and React may not re-render. You also lose the ability to roll back to a previous state.

1. Basic sort — spread a copy first:

Example:

import { useState } from 'react';

const initialFruits = ['Banana', 'Apple', 'Cherry', 'Mango'];

export default function FruitList() {
  const [fruits, setFruits] = useState(initialFruits);

  const sortAscending = () => {
    // ✅ Spread creates a new array — original state is untouched
    setFruits([...fruits].sort((a, b) => a.localeCompare(b)));
  };

  const sortDescending = () => {
    setFruits([...fruits].sort((a, b) => b.localeCompare(a)));
  };

  return (
    <>
      <button onClick={sortAscending}>Sort A  Z</button>
      <button onClick={sortDescending}>Sort Z  A</button>
      <ul>
        {fruits.map((fruit) => (
          <li key={fruit}>{fruit}</li>
        ))}
      </ul>
    </>
  );
}

2. Sort an array of objects by a property:

Example:

const [users, setUsers] = useState([
  { id: 1, name: 'Priya', age: 28 },
  { id: 2, name: 'Alice', age: 34 },
  { id: 3, name: 'Bob',   age: 22 },
]);

// Sort by age (ascending)
const sortByAge = () => {
  setUsers(prev => [...prev].sort((a, b) => a.age - b.age));
};

// Sort by name (alphabetical)
const sortByName = () => {
  setUsers(prev => [...prev].sort((a, b) => a.name.localeCompare(b.name)));
};

Try this example on CodeSandbox

↥ back to top

Q. How do you update one item in a state list immutably?

To update a single item in a state array without mutating the original, use Array.prototype.map() to return a new array where only the matching item is replaced. Every other item is returned as-is.

Example: Functional component with useState

import { useState } from 'react';

const initialTasks = [
  { id: 1, title: 'Buy groceries', done: false },
  { id: 2, title: 'Read a book',   done: false },
  { id: 3, title: 'Go for a walk', done: false },
];

export default function TaskList() {
  const [tasks, setTasks] = useState(initialTasks);

  const toggleDone = (id: number) => {
    setTasks(prevTasks =>
      prevTasks.map(task =>
        task.id === id ? { ...task, done: !task.done } : task
      )
    );
  };

  return (
    <ul>
      {tasks.map(task => (
        <li key={task.id}>
          <span style=>
            {task.title}
          </span>
          <button onClick={() => toggleDone(task.id)}>
            {task.done ? 'Undo' : 'Done'}
          </button>
        </li>
      ))}
    </ul>
  );
}
↥ back to top

Q. How do you handle very large lists in React apps?

Rendering thousands of DOM nodes at once causes slow initial paint, sluggish scrolling, and high memory usage. The core strategies are virtualization, pagination, infinite scrolling, and memoization.

1. Virtualization (windowing) — most impactful:

Only render the rows currently visible in the viewport. As the user scrolls, off-screen rows are unmounted and new ones are mounted. Libraries like react-window and react-virtual implement this efficiently.

import { List, RowComponentProps } from 'react-window';

const Row = ({ index, style }: RowComponentProps) => (
  <div style={style}>Row {index}</div>
);

export default function BigList() {
  return (
    <List
      style=
      rowCount={100000}
      rowHeight={25}
      rowComponent={Row}
      rowProps=
    />
  );
}

Install: npm install react-window

For variable-height rows use VariableSizeList; for grids use FixedSizeGrid / VariableSizeGrid.

2. Pagination — load data in pages:

Fetch and render only one page of data at a time. Users navigate between pages explicitly. This is the simplest strategy and works well for tabular data.

import { useState } from 'react';

const PAGE_SIZE = 10;

const ALL_ITEMS = Array.from({ length: 100 }, (_, i) => ({ id: i + 1, name: `Item ${i + 1}` }));

export default function PaginatedList() {
  const [page, setPage] = useState(1);
  const totalPages = Math.ceil(ALL_ITEMS.length / PAGE_SIZE);
  const visible = ALL_ITEMS.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

  return (
    <>
      <ul>{visible.map(item => <li key={item.id}>{item.name}</li>)}</ul>
      <button disabled={page === 1} onClick={() => setPage(p => p - 1)}>Prev</button>
      <button disabled={page === totalPages} onClick={() => setPage(p => p + 1)}>Next</button>
    </>
  );
}

3. Infinite scrolling — append on demand:

Load the next batch of items when the user reaches the bottom. Use the IntersectionObserver API (or a library like react-intersection-observer) to detect when a sentinel element enters the viewport.

import { useState, useRef, useCallback } from 'react';

type Item = { id: number; name: string };

const ALL_ITEMS: Item[] = Array.from({ length: 100 }, (_, i) => ({ id: i + 1, name: `Item ${i + 1}` }));
const PAGE_SIZE = 10;

export default function InfiniteList() {
  const [count, setCount] = useState(PAGE_SIZE);
  const items = ALL_ITEMS.slice(0, count);
  const hasMore = count < ALL_ITEMS.length;
  const loadMore = () => setCount(c => Math.min(c + PAGE_SIZE, ALL_ITEMS.length));

  const observer = useRef<IntersectionObserver | null>(null);

  const sentinelRef = useCallback((node: Element | null) => {
    if (observer.current) observer.current.disconnect();
    observer.current = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && hasMore) loadMore();
    });
    if (node) observer.current.observe(node);
  }, [hasMore]);

  return (
    <ul>
      {items.map((item: Item) => <li key={item.id}>{item.name}</li>)}
      {hasMore && <li ref={sentinelRef} />}
    </ul>
  );
}

4. Memoization — avoid re-rendering unchanged rows:

Combine any of the above with React.memo and useCallback so that only changed rows re-render when the parent updates.

const ListRow = React.memo(function ListRow({ item, onSelect }) {
  return <li onClick={() => onSelect(item.id)}>{item.name}</li>;
});

// In parent — stable callback reference
const handleSelect = useCallback((id) => {
  setSelectedId(id);
}, []);

Strategy comparison:

Strategy Best for Complexity
Virtualization Any large list (1k+ items visible) Medium
Pagination Tabular data, server-side data Low
Infinite scroll Social feeds, search results Medium
Memoization Preventing unnecessary re-renders Low

For most apps: virtualize if all data is in memory (e.g. a local dataset), paginate or infinite-scroll if data is fetched from a server.

↥ back to top

Q. How do Suspense/loading states integrate with list rendering?

React provides two complementary approaches for handling loading states when rendering lists: the traditional manual loading state pattern and the modern React Suspense pattern.

1. Manual loading state (classic approach)

Manage a loading boolean in state, show a spinner or skeleton while data is being fetched, then render the list once data arrives.

import { useState, useEffect } from 'react';

export default function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res => res.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err.message);
        setLoading(false);
      });
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error)   return <p>Error: {error}</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

2. React Suspense with data-fetching libraries

React.Suspense lets you declaratively specify a fallback UI while a child component is “suspended” (waiting for data). Libraries like React Query, SWR, and Relay integrate with Suspense natively.

import { Suspense } from 'react';
import { useSuspenseQuery } from '@tanstack/react-query';

// Child component — suspends automatically while fetching
function UserList() {
  const { data: users } = useSuspenseQuery({
    queryKey: ['users'],
    queryFn: () =>
      fetch('https://jsonplaceholder.typicode.com/users').then(r => r.json()),
  });

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

// Parent wraps the list in Suspense and provides a fallback
export default function App() {
  return (
    <Suspense fallback={<p>Loading users...</p>}>
      <UserList />
    </Suspense>
  );
}
↥ back to top

Q. How does rendering lists differ in Server Components vs Client Components

React 18+ (with frameworks like Next.js 13+) introduced Server Components (RSC) and retained Client Components. The two render lists in fundamentally different environments and with different constraints.

Core distinction

  Server Component Client Component
Runs on Server (Node.js, Edge runtime) Browser
Can use hooks (useState, useEffect) ❌ No ✅ Yes
Can fetch data directly (DB, filesystem) ✅ Yes ❌ No (needs API)
Ships JS to the browser ❌ No (HTML only) ✅ Yes
Supports interactivity (click, input) ❌ No ✅ Yes
Default in Next.js App Router ✅ Yes Requires "use client" directive

1. Rendering a list in a Server Component

Server Components can be async and fetch data directly from a database or API — no useEffect, no loading state, no client-side JavaScript shipped for the list itself.

// app/users/page.tsx  (Next.js App Router — Server Component by default)

async function UsersPage() {
  // Direct database or API call — runs only on the server
  const res = await fetch('https://jsonplaceholder.typicode.com/users', {
    cache: 'force-cache', // or 'no-store' for dynamic data
  });
  const users = await res.json();

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UsersPage;

2. Rendering a list in a Client Component

Client Components are required whenever the list is interactive — sorting, filtering, selecting, paginating on the client, or using any React hook.

'use client'; // marks this file as a Client Component

import { useState } from 'react';

type User = { id: number; name: string };

const USERS: User[] = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

export default function FilterableList() {
  const [query, setQuery] = useState('');

  const filtered = USERS.filter(user =>
    user.name.toLowerCase().includes(query.toLowerCase())
  );

  return (
    <>
      <input
        value={query}
        onChange={e => setQuery(e.target.value)}
        placeholder="Search users…"
      />
      <ul>
        {filtered.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </>
  );
}
↥ back to top

# 9. React RESTful API


Q. How to make a API calls in React?

In React, API calls are typically made using the Fetch API (built-in) or Axios (a popular third-party library). These calls are usually placed within the useEffect hook to trigger when a component mounts or when specific dependencies change

1. Using the Fetch API (Built-in)

The native fetch() method requires two steps: one to make the request and another to parse the response into JSON

Example:

/** 
 * API call using fetch()
 */
import React, { useState, useEffect } from 'react';

// Example fetching data inside useEffect
useEffect(() => {
  fetch('https://jsonplaceholder.typicode.com/users')
    .then(response => {
      if (!response.ok) throw new Error('Network response was not ok');
      return response.json();
    })
    .then(data => setUsers(data))
    .catch(err => setError(err.message));
}, []);

2. Using Axios (Recommended for Larger Apps)

Axios simplifies the process by automatically parsing JSON and throwing errors for non-2xx status codes.

Example:

import axios from 'axios';

// Example using Axios inside useEffect
useEffect(() => {
  axios.get('https://jsonplaceholder.typicode.com/users')
    .then(response => setUsers(response.data))
    .catch(err => setError(err.message));
}, []);

Key Differences

Best Practices:

Try this example on CodeSandbox

↥ back to top

Q. How to display API data using Axios in React?

Axios is a promise based HTTP client for making HTTP requests from a browser to any web server. Use Axios inside useEffect, save response data in state, and render it with map.

Example:

/**
 * GET Request using Axios
 */
import { useEffect, useState } from "react";
import axios from "axios";

interface User {
  id: number;
  name: string;
  email: string;
}

export default function App() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await axios.get("https://jsonplaceholder.typicode.com/users");
        setUsers(response.data);
      } catch (error) {
        setError("Failed to fetch users: " + (error as Error).message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>{error}</p>;

  return (
    <div>
      <h2>User List</h2>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            {user.name} - {user.email}
          </li>
        ))}
      </ul>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to make a post call using Axios in React?

Use Axios post inside a submit handler, then update state with the response.

Example:

/**
 * POST Request using Axios
 */
import { useState } from "react";
import axios, { AxiosError } from "axios";

interface CreatedUser {
  id: number;
  name: string;
}

export default function CreateUser() {
  const [name, setName] = useState("");
  const [result, setResult] = useState<CreatedUser | null>(null);
  const [error, setError] = useState("");

  const handleSubmit = async (event: React.SubmitEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError("");
    setResult(null);

    try {
      const response = await axios.post(
        "https://jsonplaceholder.typicode.com/users",
        { name } // request body
      );
      setResult(response.data);
      setName("");
    } catch (err) {
      const axiosErr = err as AxiosError;
      setError("Failed to create user" + (axiosErr.response ? `: ${axiosErr.response.statusText}` : ""));
    }
  };

  return (
    <div>
      <h2>Create User</h2>

      <form onSubmit={handleSubmit}>
        <input
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Enter name"
          required
        />
        <button type="submit">Submit</button>
      </form>

      {error && <p>{error}</p>}

      {result && (
        <div>
          <h3>Created:</h3>
          <p>ID: {result.id}</p>
          <p>Name: {result.name}</p>
        </div>
      )}
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. What are the benefits of using Axios() over Fetch() for making http requests?

Axios is a third-party library that offers several high-level conveniences for handling HTTP requests, whereas the Fetch API is a native, low-level browser tool that often requires more manual setup.

Key Benefits of Axios

↥ back to top

Q. How does Axios Interceptors work in React?

Axios Interceptors act as middleware for your HTTP requests and responses. They allow you to define global logic that executes automatically before a request is sent to the server or after a response is received, but before it reaches your component's .then() or .catch() blocks.

1. Request Interceptor:

Used to modify outgoing request configurations. Common tasks include automatically attaching Authorization headers (like JWT tokens) or logging request metadata for debugging.

Example:

axios.interceptors.request.use(
  (request) => {
    const token = localStorage.getItem('token');
    if (token) {
      request.headers['Authorization'] = `Bearer ${token}`;
    }
    return request; // must return the request
  },
  (error) => Promise.reject(error)
);

2. Response Interceptor:

Used to process incoming data or handle errors globally. This is ideal for centralized error management, such as redirecting a user to login if they receive a 401 Unauthorized error or refreshing expired tokens.

Example:

axios.interceptors.response.use(
  (response) => response, // pass through successful responses
  (error) => {
    if (error.response?.status === 401) {
      // redirect to login
    }
    return Promise.reject(error);
  }
);

Implementation in React:

Typically configured once in a shared axiosInstance.js file or in a top-level component/effect:

Example:

// axiosInstance.js
import axios from 'axios';

const api = axios.create({ baseURL: 'https://api.example.com' });

api.interceptors.request.use((config) => {
  config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
  return config;
});

api.interceptors.response.use(
  (res) => res,
  (err) => {
    if (err.response?.status === 403) console.error('Forbidden');
    return Promise.reject(err);
  }
);

export default api;
↥ back to top

Q. How to do caching in React?

Caching in React is typically handled through three distinct layers: Memoization (internal logic), Data Fetching (network requests), and Browser/Persistent Storage (long-term data)

1. In-Component Memoization

These built-in hooks prevent expensive calculations or component re-renders when inputs haven't changed.

Example:

const sortedList = useMemo(() => {
  return items.sort((a, b) => a.price - b.price);
}, [items]);

It memoizes a function instance, preventing unnecessary re-renders of child components.

Example:

const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

Example:

const MyComponent = React.memo(({ name }) => {
  return <div>{name}</div>;
});

2. Data & Network Caching

Managing API responses effectively is the most common “caching” need in React.

Example:

// TanStack Query example
const { data } = useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
  staleTime: 5 * 60 * 1000, // cache for 5 minutes
});

Example:

import { cache } from 'react';

const getUser = cache(async (id) => {
  return await db.users.findById(id);
});

Example:

import useSWR from 'swr';

interface User {
  id: number;
  name: string;
  email: string;
  phone: string;
}

// 1. Define a fetcher function (can use fetch, axios, etc.)
const fetcher = (url: string) => fetch(url).then((res) => res.json());

function Profile() {
  // 2. Use the hook with a unique key (URL) and the fetcher
  const { data, error, isLoading } = useSWR<User[]>('https://jsonplaceholder.typicode.com/users', fetcher);

  // 3. Handle loading and error states
  if (error) return <div>Failed to load</div>;
  if (isLoading) return <div>Loading...</div>;

  // 4. Render data
  return (
    <>
      <h1>Users</h1>
      <ul>
        {data?.map((user) => (
          <li key={user.id}>
            <strong>{user.name}</strong> — {user.email} — {user.phone}
          </li>
        ))}
      </ul>
    </>
  );
}

export default Profile;

3. Persistent & Browser Caching

For data that must survive page refreshes or be available offline.

↥ back to top

Q. In which lifecycle event do you make AJAX requests in React?

1. Functional Component (Modern Approach)

The useEffect hook is used to perform side effects like data fetching. By passing an empty array [] as the second argument, the fetch runs only once when the component mounts.

Example:

import { useState, useEffect } from 'react';

interface User {
  id: number;
  name: string;
}

function UserProfile() {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    // AJAX request starts here
    fetch('https://jsonplaceholder.typicode.com/users/1')
      .then(res => res.json())
      .then(data => setUser(data)); // Updates state once data is received
  }, []); // Run only on mount

  return <div>{user ? user.name : "Loading..."}</div>;
}

export default UserProfile;

2. Class Component (Legacy Approach)

In a class component, you place the request in componentDidMount(). This ensures the component is already in the DOM before the network request starts.

Example:

import React, { Component } from 'react';

class UserProfile extends Component {
  state = { user: null };

  componentDidMount() {
    // AJAX request starts here
    fetch('https://api.example.com/user')
      .then(res => res.json())
      .then(data => this.setState({ user: data }));
  }

  render() {
    return <div>{this.state.user ? this.state.user.name : "Loading..."}</div>;
  }
}

Try this example on CodeSandbox

↥ back to top

Q. How to use async await in React?

In React, you can use async/await to make your asynchronous code cleaner and more readable than standard promise chains. However, how you implement it differs slightly between functional and class components.

Functional Components (useEffect)

You cannot make the useEffect callback function itself async. This is because useEffect expects to return either nothing or a synchronous cleanup function, but an async function always returns a Promise.

To work around this, define an async function inside the effect and call it immediately.

Example:

import { useEffect, useState } from "react";

interface User {
  id: number;
  name: string;
}

export default function Users() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  useEffect(() => {
    let ignore = false;
    // Define the async function
    async function fetchUsers() {
      try {
        setLoading(true);
        const res = await fetch("https://jsonplaceholder.typicode.com/users");
        if (!res.ok) throw new Error("Request failed");
        const data = await res.json();
        if (!ignore) setUsers(data);
      } catch (err) {
        if (!ignore) setError(err instanceof Error ? err.message : "Unknown error");
      } finally {
        if (!ignore) setLoading(false);
      }
    }

    fetchUsers();

    return () => { ignore = true; };
  }, []); // Empty array runs this only once on mount

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return <ul>{users.map((u) => <li key={u.id}>{u.name}</li>)}</ul>;
}

2. Class Components (componentDidMount)

async componentDidMount() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    this.setState({ data });
  } catch (error) {
    console.error("Fetch failed", error);
  }
}

Try this example on CodeSandbox

↥ back to top

Q. How RxJS is used in React for state management?

RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code. Reactive programming is an event-based paradigm that allows us to run asynchronous sequences of events as soon as data is pushed to a consumer.

Core Concept:

RxJS Terminology:

Example:

Here is a simple example of a Global Counter using a BehaviorSubject. This pattern allows any component to read or update the state without using Props or Context.

1. The Store (store.js)

We create a BehaviorSubject to hold the value and a simple function to update it.

import { BehaviorSubject } from 'rxjs';

// Initialize with 0
const counterSubject = new BehaviorSubject(0);

export const counterStore = {
  // Observable for components to subscribe to
  counter$: counterSubject.asObservable(),
  
  // Method to update the state
  increment: () => counterSubject.next(counterSubject.value + 1),
  decrement: () => counterSubject.next(counterSubject.value - 1)
};

2. The React Component (Counter.js)

We use useEffect to “bridge” the RxJS stream into React's local state so the UI re-renders.

import React, { useState, useEffect } from 'react';
import { counterStore } from './store';

export function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Subscribe to changes
    const subscription = counterStore.counter$.subscribe(setCount);

    // CRITICAL: Clean up subscription on unmount
    return () => subscription.unsubscribe();
  }, []);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={counterStore.increment}>+</button>
      <button onClick={counterStore.decrement}>-</button>
    </div>
  );
}

Note:

Use RxJS when you truly need stream composition; for simple app state, React context/useReducer may be simpler.

Reference:

↥ back to top

# 10. REACT FORMS


Q. How dynamically generate menu options for <select> from an array?

Example:

import { useState } from "react";

export default function ColorPicker() {
  const colors = ["Red", "Green", "Blue", "Black"];
  const [selectedColor, setSelectedColor] = useState("");

  return (
    <div>
      <label htmlFor="color">Choose a color: </label>
      <select
        id="color"
        value={selectedColor}
        onChange={(e) => setSelectedColor(e.target.value)}
      >
        <option value="">-- Select color --</option>
        {colors.map((color) => (
          <option key={color} value={color}>
            {color}
          </option>
        ))}
      </select>

      <p>Selected: {selectedColor || "None"}</p>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How would you create a form in React?

Create it as a controlled form: keep each input value in state, update state on change, and handle submit in one function.

Example:

import { useState } from "react";

const countries = ["Austria", "India", "Italy", "Russia", "United States"];

export default function App() {
  const [form, setForm] = useState({
    email: "",
    password: "",
    country: "",
    acceptedTerms: false,
  });

  const handleChange = (event) => {
    const { name, value, type, checked } = event.target;
    setForm((prev) => ({
      ...prev,
      [name]: type === "checkbox" ? checked : value,
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log("Submitted data:", form);
    // call API here
  };

  return (
    <form onSubmit={handleSubmit}>
      <h2>Sign Up</h2>

      <label>
        Email
        <input
          type="email"
          name="email"
          value={form.email}
          onChange={handleChange}
          required
        />
      </label>

      <label>
        Password
        <input
          type="password"
          name="password"
          value={form.password}
          onChange={handleChange}
          required
          minLength={6}
        />
      </label>

      <label>
        Country
        <select
          name="country"
          value={form.country}
          onChange={handleChange}
          required
        >
          <option value="">Select country</option>
          {countries.map((country) => (
            <option key={country} value={country}>
              {country}
            </option>
          ))}
        </select>
      </label>

      <label>
        <input
          type="checkbox"
          name="acceptedTerms"
          checked={form.acceptedTerms}
          onChange={handleChange}
        />
        I accept terms
      </label>

      <button type="submit" disabled={!form.acceptedTerms}>
        Submit
      </button>
    </form>
  );
}

Output:

React Form

Try this example on CodeSandbox

↥ back to top

Q. Why You Should Choose React Hook Form Over Formik and Redux-Form?

Below are the main reasons to recommend React Hook Form Over Formik and Redux-Form,

1. Isolate Component Re-Rendering:

React Hook Form isolates the component and avoids the other components from re-rending. This feature will improve the performance by avoiding unwanted rendering in other child components. However, libraries like Formik and Redux-Form re-render the other child components along with the form component.

2. Reduce Rendering:

Besides isolating the component, it also limits its own (form components) form re-rendering on particular events such as onChange, onBlur, etc.

3. Faster Mounting:

Mounting time is about 13% faster than Formik and 25% faster than Redux-Form. In other words, the form's DOM elements will be inserted into the DOM tree quicker, leading to fast rendering compared with other libraries.

4. Input Change Subscriptions:

React Hook Form allows you to subscribe to each input element without going through the re-rendering of each element inside the form component.

5. Typescript Support:

React Hook Form is built with TypeScript and can define a FormData type to support form values.

6. Less Code to Maintain:

The React Hook Form provides a hook called useForm(), consisting of methods and props handleSubmit, register, and errors. They would handle the submit events, the input via refs using register, and display any errors. However, in the other two libraries, you need to write your custom handlers for events and validations.

↥ back to top

Q. What are controlled and uncontrolled components in React?

In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself.

1. Controlled Components:

In a controlled component, the form data is handled by the state within the component. The state within the component serves as “the single source of truth” for the input elements that are rendered by the component.

2. Uncontrolled Components:

Uncontrolled components act more like traditional HTML form elements. The data for each input element is stored in the DOM, not in the component. Instead of writing an event handler for all of your state updates, It uses ref to retrieve values from the DOM. Refs provide a way to access DOM nodes or React elements created in the render method.

Example:

import { useRef, useState } from "react";

export default function FormExamples() {
  // Controlled state
  const [name, setName] = useState("");

  // Uncontrolled ref
  const ageRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(`Controlled name: ${name}`);
    console.log(`Uncontrolled name: ${name}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <h3>Controlled Input</h3>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter name"
      />

      <h3>Uncontrolled Input</h3>
      <input
        type="number"
        ref={ageRef}
        defaultValue="18"
        placeholder="Enter age"
      />

      <button type="submit">Submit</button>
    </form>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How do you set default value for uncontrolled components?

React provides defaultValue attribute that pre-populate the input field with the default Value without overriding any value input by the user.

Example:

/**
 * React defaultValue
 */
import { useRef } from "react";

export default function UncontrolledForm() {
  const nameRef = useRef(null);
  const newsletterRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(
      `Name: ${nameRef.current.value}, Newsletter: ${newsletterRef.current.checked}`
    );
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        ref={nameRef}
        type="text"
        defaultValue="Pradeep"   // initial value only
      />

      <label>
        <input
          ref={newsletterRef}
          type="checkbox"
          defaultChecked={true}  // initial checked state
        />
        Subscribe
      </label>

      <button type="submit">Submit</button>
    </form>
  );
}

Try this example on CodeSandbox

↥ back to top

# 11. REACT HOOKS


Q. What are React Hooks?

React Hooks are in-built functions that let you “hook into” React features like state, lifecycle behavior, context, and more from function components (without writing class components).

Rules of Hooks:

Built-in Hooks:

Hooks Description
useState() To manage states. Returns a stateful value and an updater function to update it.
useEffect() To manage side-effects like API calls, subscriptions, timers, mutations, and more.
useContext() To return the current value for a context.
useReducer() A useState alternative to help with complex state management.
useCallback() It returns a memorized version of a callback to help a child component not re-render unnecessarily.
useMemo() It returns a memoized value that helps in performance optimizations.
useRef() It returns a ref object with a .current property. The ref object is mutable. It is mainly used to access a child component imperatively.
useImperativeHandle() It customizes the instance value that is exposed to parent components when using ref.
useLayoutEffect() It fires at the end of all DOM mutations. It's best to use useEffect as much as possible over this one as the useLayoutEffect fires synchronously.
useDebugValue() Helps to display a label in React DevTools for custom hooks.

Example:

/**
 * useState() Hooks
 */
import { useState } from "react";

function App() {
  const [isButtonClicked, setIsButtonClicked] = useState(false);

  return (
    <button onClick={() => setIsButtonClicked(!isButtonClicked)}>
      {isButtonClicked ? "Clicked" : "Click Me, Please"}
    </button>
  );
}

export default App;

Try this example on CodeSandbox

↥ back to top

Q. What are advantages of using React Hooks?

↥ back to top

Q. How to create custom Hooks?

React also allows us to create custom Hooks with unique features that extracts component logic into reusable functions.

A custom Hooks has following features:

Example: Custom Hook - useFetch()

/**
 * Custom Hook
 */
import { useState, useEffect } from "react";

const useFetch = (url: string) => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => setData(data));
  }, [url]);

  return [data];
};

export default useFetch;
/**
 * App Component
 */
import "./styles.css";
import useFetch from "./useFetch";

export default function App() {
  // custom hook
  const [data] = useFetch("https://jsonplaceholder.typicode.com/todos");
  return (
    <>
      {data &&
        data.map((item) => {
          return <p key={item.id}>{item.title}</p>;
        })}
    </>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to fetch data with React Hooks?

The two main hooks used for fetching data are:

Example:

/**
 * useState() and useEffect() Hooks
 */
import { useState, useEffect } from "react";

interface User {
  id: number;
  login: string;
}

function App() {
  const [users, setUsers] = useState<User[]>([]);

  useEffect(() => {
    fetch("https://api.github.com/users")
      .then((response) => response.json())
      .then((data) => setUsers(data));
  }, []); // Empty dependency array = run once on mount

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.login}</li>
      ))}
    </ul>
  );
}
export default App;

Try this example on CodeSandbox

↥ back to top

Q. Do Hooks replace render props and higher-order components?

In most cases, yes, Hooks replace the need for render props and higher-order components (HOCs). While they haven't made these patterns obsolete, Hooks are now the recommended default for sharing stateful logic in modern React applications.

Why Hooks are Preferred

When You Might Still Use HOCs or Render Props

Despite the shift to Hooks, these patterns still have specific use cases:

Higher-Order Components:

↥ back to top

Q. How to compare oldValues and newValues on React Hooks useEffect?

Use a ref to store the previous value. Refs persist across renders and updating them does not trigger a re-render, which makes them perfect for old vs new comparisons in useEffect.

Example:

// Custom Hook
const usePrevious = (value) => {
  const ref = useRef();
   
  // Store the current value in the ref AFTER every render
  useEffect(() => {
    ref.current = value;
  }, [value]); // Only update when the value actually changes

  // Return the value from the PREVIOUS render cycle
  return ref.current;
};
import { useEffect, useRef, useState } from "react";

function Example() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  useEffect(() => {
    const prevCount = prevCountRef.current;

    if (prevCount !== undefined && prevCount !== count) {
      console.log("old:", prevCount, "new:", count);
    }

    // update ref after comparison
    prevCountRef.current = count;
  }, [count]);

  return <button onClick={() => setCount((c) => c + 1)}>+1</button>;
}

We create a custom usePrevious hook that accepts the current state value as input and returns the value from the previous render. Inside the hook, useRef stores that value without causing a re-render, and useEffect updates ref.current after each render so it is available as the previous value on the next render.

Try this example on CodeSandbox

↥ back to top

Q. How to re-render the view when the browser is resized?

To re-render a React component when the browser is resized, you can use the useEffect hook to listen to the resize event. When this event fires, you update the component's state, which automatically triggers a re-render.

Example:

import { useState, useEffect } from 'react';

/**
 * Custom hook that tracks the current browser window dimensions.
 * Updates on every resize event and cleans up the listener on unmount.
 * @returns The current `{ width, height }` of the window, or `undefined` before first mount.
 */
function useWindowSize() {
  const [windowSize, setWindowSize] = useState<{ width: number; height: number } | undefined>(
    undefined
  );

  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    handleResize();
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;
}
/**
 * Page component that displays the current window width and height.
 */
export default function Page() {
  const size = useWindowSize();

  return (
    <div>
      <p>Width: {size?.width}</p>
      <p>Height: {size?.height}</p>
    </div>
  );
}
↥ back to top

Q. How can I force a component to re-render with hooks in React?

The useState() or useReducer() hooks can be used to force a React component to rerender.

Example:

/**
 * Rerender Component using useState()
 */
import { useState } from "react";

function Example() {
  const [, setTick] = useState(0);

  const forceRender = () => {
    setTick((tick) => tick + 1);
  };

  return <button onClick={forceRender}>Re-render</button>;
}
/**
 * Rerender Component using useReducer()
 */
import { useReducer } from "react";

function Example() {
  const [, forceRender] = useReducer((count) => count + 1, 0);

  return <button onClick={forceRender}>Re-render</button>;
}

Try this example on CodeSandbox

↥ back to top

Q. What is useState() in React?

The useState() is a built-in React Hook that allows to have state variables in functional components. State is data that needs to be tracked within an application, and when a state variable changes, React automatically re-renders the component to display the updated value.

Example:

import { useState } from 'react';

function Counter() {
  // Declares a state variable 'count' initialized to 0, and a function 'setCount' to update it
  const [count, setCount] = useState(0); 

  return (
    <>
      <p>You clicked {count} times</p>
      {/* The onClick handler calls setCount to update the state, triggering a re-render */}
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </>
  );
}

The useState() function takes as argument a value for the initial state. In this case, the count starts out with 0. In addition, the hook returns an array of two values: count and setCount.

↥ back to top

Q. Why do we use array destructuring in useState?

We use array destructuring because useState returns a pair (an array with exactly two items), and destructuring is the cleanest way to give those items custom names in a single line.

The useState hook allows us to make our function components stateful. When called, useState() returns an array of two items. The first being our state value and the second being a function for setting or updating that value.

Example: State with Various Data Types

const [count, setCount] = useState(0)
const [color, setColor] = useState('#526b2d')
const [isHidden, setIsHidden] = useState(true)
const [products, setProducts] = useState([])
const [user, setUser] = useState({
    name: '',
    age: '',
    email: '',
})
↥ back to top

Q. What is useReducer() in React?

useReducer() is a React Hook for managing state with a reducer function, especially when state logic is complex or depends on previous state.

It accepts a reducer function with the application initial state, returns the current application state, then dispatches a function.

Syntax:

The useReducer Hook returns an array with exactly two values: the current state and a dispatch function

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

Example:

import { useReducer } from 'react'

type Action = 'increment' | 'decrement' | 'reset'

const initialState = 0

/**
 * Reducer function for managing a counter state.
 * @param state - The current counter value.
 * @param action - The action to perform: 'increment', 'decrement', or 'reset'.
 * @returns The updated counter value.
 */
const reducer = (state: number, action: Action) => {
  switch (action) {
    case 'increment': return state + 1
    case 'decrement': return state - 1
    case 'reset': return 0
    default: throw new Error('Unexpected Action!')
  }
}

/**
 * Component that demonstrates useReducer with increment, decrement, and reset actions.
 */
const ReducerExample = () => {
  const [count, dispatch] = useReducer(reducer, initialState)
  return (
    <div>
      {count}
      <button onClick={() => dispatch('increment')}>+1</button>
      <button onClick={() => dispatch('decrement')}>-1</button>
      <button onClick={() => dispatch('reset')}>reset</button>
    </div>
  )
}

export default ReducerExample

Here, we first define an initialState and a reducer. When a user clicks a button, it will dispatch an action which updates the count and the updated count will be displayed. We could define as many actions as possible in the reducer, but the limitation of this pattern is that actions are finite.

↥ back to top

Q. When to use useReducer vs useState Hooks in React?

Use useState when:

Use useReducer when:

↥ back to top

Q. How does React renderer work exactly when we call setState?

When you call setState, the React renderer doesn't immediately touch the real DOM. Instead, it triggers a two-phase process managed by the Fiber reconciler to efficiently determine and apply only the necessary changes

1. The Render Phase (Asynchronous & Interruptible)

This phase is purely internal and does not produce user-visible changes.

2. The Commit Phase (Synchronous & Non-Interruptible)

Once the entire tree has been processed and the “effect list” is complete, React enters the commit phase.

Key Performance Features

↥ back to top

Q. What is a Webhook in React?

Webhooks provide a mechanism where by a server-side application can notify a client-side application when a new event (that the client-side application might be interested in) has occurred on the server.

These are HTTP-based callbacks that allow a backend server to “push” real-time data to another system when a specific event occurs (like a successful payment or a new GitHub commit).

How Webhooks Work with React

Because webhooks require a permanent URL (endpoint) to receive incoming POST requests, they cannot be hosted directly inside a React frontend. A standard integration works as follows:

Common Use Cases in React Apps

↥ back to top

Q. Explain is useCallback(), useMemo(), useImperativeHandle(), useLayoutEffect(), useDebugValue() in React?

1. useCallback():

React's useCallback() Hook can be used to optimize the rendering behavior of your React function components. The useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed.

This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).

Example:

/**
 * Demonstrates useCallback() to memoize a function reference.
 * The memoized `increment` callback is only recreated when `counter` changes, preventing unnecessary re-renders and function calls.
 */
import { useState, useCallback, useEffect } from "react";

const count = new Set();

function App() {
  const [counter, setCounter] = useState(0);

  const increment = useCallback(() => {
    setCounter(counter + 1);
  }, [counter]);

  useEffect(() => {
    count.add(increment);
    console.log(count.size);
  }, [increment]);

  return (
    <>
      <h1>useCallback Hook Example</h1>
      <h2>Function Call: {count.size}</h2>
      <button onClick={increment}>Increment</button>
    </>
  );
}

export default App;

Try this example on CodeSandbox

2. useMemo():

The useMemo() is similar to useCallback() except it allows you to apply memoization to any value type. It does this by accepting a function which returns the value and then that function is only called when the value needs to be retrieved.

Example:

import React from 'react'

const users = [
  { id: '101', name: 'Dennis' },
  { id: '102', name: 'Alice' },
  { id: '103', name: 'Bob' },
  { id: '104', name: 'Carol' },
  { id: '105', name: 'Dave' }
]

/**
 * App component that renders a searchable list of users.
 * Uses `useMemo` to memoize the filtered user list, recomputing
 * only when the search query changes.
 */
const App = () => {
  const [search, setSearch] = React.useState('')

  const filteredUsers = React.useMemo(
    () => users.filter((user) => user.name.toLowerCase().includes(search.toLowerCase())),
    [search]
  )

  return (
    <div>
      <input
        type="text"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder="Search users"
      />
      <ul>
        {filteredUsers.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  )
}

export default App

3. useImperativeHandle():

useImperativeHandle() customizes the instance value that is exposed to parent components when using ref. As always, imperative code using refs should be avoided in most cases. useImperativeHandle should be used with forwardRef.

import { useRef, useImperativeHandle, forwardRef } from 'react'

interface InputHandle {
  focus: () => void
  clear: () => void
}

/**
 * A custom input component that exposes `focus` and `clear` methods
 * to parent components via `useImperativeHandle`.
 */
const CustomInput = forwardRef<InputHandle>((_, ref) => {
  const inputRef = useRef<HTMLInputElement>(null)

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current?.focus()
    },
    clear() {
      if (inputRef.current) inputRef.current.value = ''
    },
  }))

  return <input ref={inputRef} type="text" placeholder="Type something..." />
})

CustomInput.displayName = 'CustomInput'

/**
 * App component that uses a ref to imperatively call `focus` and `clear`
 * on the CustomInput child component.
 */
const App = () => {
  const inputRef = useRef<InputHandle>(null)

  return (
    <div>
      <CustomInput ref={inputRef} />
      <button onClick={() => inputRef.current?.focus()}>Focus</button>
      <button onClick={() => inputRef.current?.clear()}>Clear</button>
    </div>
  )
}

export default App

4. useLayoutEffect():

useLayoutEffect

This runs synchronously immediately after React has performed all DOM mutations. This can be useful if you need to make DOM measurements (like getting the scroll position or other styles for an element) and then make DOM mutations or trigger a synchronous re-render by updating state.

As far as scheduling, this works the same way as componentDidMount and componentDidUpdate. Your code runs immediately after the DOM has been updated, but before the browser has had a chance to “paint” those changes (the user doesn't actually see the updates until after the browser has repainted).

Example:

import { useRef, useLayoutEffect } from 'react'

/**
 * Demonstrates useLayoutEffect() to measure a DOM element\'s width
 * synchronously after the browser has performed layout, before paint.
 */
const App = () => {
  const boxRef = useRef<HTMLDivElement>(null)
  const labelRef = useRef<HTMLSpanElement>(null)

  useLayoutEffect(() => {
    const measure = () => {
      if (boxRef.current && labelRef.current) {
        const width = boxRef.current.getBoundingClientRect().width
        labelRef.current.textContent = `Box width: ${Math.round(width)}px`
      }
    }

    measure()
    window.addEventListener('resize', measure)
    return () => window.removeEventListener('resize', measure)
  }, [])

  return (
    <div>
      <div ref={boxRef} style=>
        Resize the window
      </div>
      <span ref={labelRef} />
    </div>
  )
}

export default App

useLayoutEffect vs useEffect:

5. useDebugValue():

useDebugValue() can be used to display a label for custom hooks in React DevTools.

Example:

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null)

  // ...

  // Show a label in DevTools next to this Hook
  useDebugValue(isOnline ? 'Online' : 'Offline')

  return isOnline
}

Note::

↥ back to top

Q. What is the difference between useEffect() and useLayoutEffect() hooks?

The main difference between the useEffect() hook and the useLayoutEffect() hook is that the useEffect() hook serves asynchronously, whereas the useLayoutEffect() hook works synchronously.

After all DOM mutations have been completed by React, useLayoutEffect executes synchronously. If you need to measure the DOM (for example, to determine the scroll position or other styles for an element) and then modify the DOM or cause a synchronous re-render by changing the state, this can be helpful.

1. useEffect():

2. useLayoutEffect():

↥ back to top

Q. How to Memoize Components in React?

If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState, useReducer or useContext Hook in its implementation, it will still rerender when state or context change.

Example: Let's take an example of search functionality. In the example below, the App component contains:

import { useState, useMemo } from 'react';

const fruits = ['apple', 'orange', 'banana'];

/**
 * App component that renders a searchable fruit list.
 * Uses `useMemo` to memoize the filtered results, recomputing
 * only when the search query changes.
 */
function App() {
  const [query, setQuery] = useState('');

  const filteredFruits = useMemo(
    () => fruits.filter((fruit) => fruit.includes(query.toLowerCase())),
    [query]
  );

  return (
    <div>
      <input
        type="text"
        placeholder="Search fruits..."
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <ul>
        {filteredFruits.map((fruit) => (
          <li key={fruit}>{fruit}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

Try this example on CodeSandbox

↥ back to top

Q. How to prevent unnecessary updates using React.memo()?

The React.memo() is a higher-order component that will memoize your component, very similar to PureComponent. It will shallowly compare current and new props of the component, and if nothing changes, React will skip the rendering of that component.

Key rules to prevent unnecessary updates:

Example:

// Memo.js
const Text = (props) => {
  console.log(`Text Component`);
  return <div>Text Component re-render: {props.count} times </div>;
};

const MemoText = React.memo(
  (props) => {
    console.log(`MemoText Component`);
    return <div>MemoText Component re-render: {props.count} times </div>;
  },
  (preprops, nextprops) => true
);

// App.js
const App = () => {
  console.log(`App Component`);
  const [count, setCount] = useState(0);
  return (
    <>
      <h2>This is function component re-render: {count} times </h2>
      <Text count={count} />
      <MemoText count={count} />
      <br />
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        CLICK ME
      </button>
    </>
  );
};

Try this example on CodeSandbox

↥ back to top

# 12. REACT CONTEXT


Q. What is Context API in React?

The React Context API allows you to share data across the component tree without manually passing props at every level (avoiding “prop drilling”).

Context API

Core Concepts:

Common Use Cases:

Example:

/**
 * Counter Component
 */
const { useState, useContext } = React;

const CountContext = React.createContext();

function Counter() {
  const { count, increase, decrease } = useContext(CountContext);
  return (
    <h2>
      <button onClick={decrease}>Decrement</button>
      <span className="count">{count}</span>
      <button onClick={increase}>Increment</button>
    </h2>
  );
}
/**
 * App Component
 */
function App() {
  const [count, setCount] = useState(0);

  const increase = () => {
    setCount(count + 1);
  };
  const decrease = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <CountContext.Provider value=8>
        <Counter />
      </CountContext.Provider>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How do you solve performance corner cases while using context?

Performance issues in the React Context API typically stem from unnecessary re-renders — when the context value changes, every component that consumes that context (via useContext) will re-render, even if it only uses a piece of the data that didn't change.

Here are the primary ways to solve these performance corner cases:

1. Split Your Contexts

The most effective way to prevent unnecessary renders is to break a large, multi-purpose context into several smaller, highly specific ones.

2. Separate State and Dispatch

If you are using a useReducer or useState pattern, components that only need the “setter” (dispatch) function should not re-render when the “getter” (state) changes.

3. Stabilize the Context Value

If you pass an object literal directly into the value prop (e.g., value=), React sees a “new” object on every render of the provider, triggering all consumers to update.

4. Optimize with Component Composition

You can “short-circuit” re-renders by moving the context consumption as far down the tree as possible.

5. Advanced: Selectors and External Stores

For massive applications where these methods aren't enough, consider these “pro” alternatives:

Example:

/**
 * Counter Component
 *
 * Consumes CountContext to display the current count value
 * and provides Increment/Decrement buttons to update it.
 */
import { createContext, useContext } from 'react';

interface CountContextType {
  count: number;
  increase: () => void;
  decrease: () => void;
}

export const CountContext = createContext<CountContextType | undefined>(undefined);

function Counter() {
  const { count, increase, decrease } = useContext(CountContext) as CountContextType;
  return (
    <h2>
      <button onClick={decrease}>Decrement</button>
      <span className="count"> {count} </span>
      <button onClick={increase}>Increment</button>
    </h2>
  );
}

export default Counter;
/**
 * App Component
 *
 * Root page component that manages the counter state and provides
 * it via CountContext to the Counter child component.
 * Uses useCallback to stabilize handlers and useMemo to avoid
 * unnecessary context re-renders.
 */
import { useState, useMemo, useCallback } from 'react';
import Counter, { CountContext } from './child';

function App() {
  const [count, setCount] = useState(0);

  const increase = useCallback(() => setCount(prev => prev + 1), []);
  const decrease = useCallback(() => setCount(prev => prev - 1), []);

  const contextValue = useMemo(() => ({ count, increase, decrease }), [count, increase, decrease]);

  return (
    <div>
      <CountContext.Provider value={contextValue}>
        <Counter />
      </CountContext.Provider>
    </div>
  );
}

export default App;
↥ back to top

Q. What is the purpose of default value in context?

The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Passing undefined as a Provider value does not cause consuming components to use defaultValue.

Purpose:

Example:

/**
 * Default value in Context API
 */
import { createContext, useContext } from "react";

const Context = createContext("Default Value");

/**
 * Child1 Component
 */
function Child1() {
  const context = useContext(Context);
  return <h2>Child1: {context}</h2>;
}

/**
 * Child2 Component
 */
function Child2() {
  const context = useContext(Context);
  return <h2>Child2: {context}</h2>;
}

/**
 * App Component
 */
export default function App() {
  return (
    <>
      <Context.Provider value={"Initial Value"}>
        <Child1 /> {/* Child inside Provider will get "Initial Value" */}
      </Context.Provider>
      <Child2 /> {/* Child outside Provider will get "Default Value" */}
    </>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to use contextType react?

The ContextType property on a class component can be assigned a Context object created by React.createContext() method. This property lets you consume the nearest current value of the context using this.context. We can access this.context in any lifecycle method including the render functions.

Key Concept:

Example:

/**
 * ContextType Example
 *
 * Demonstrates class-based context consumption using static contextType.
 * ThemeContext provides a "dark" theme value to the Header component,
 * which reads it via this.context.
 */
import React from "react";

const ThemeContext = React.createContext("light");

class Header extends React.Component {
  static readonly contextType = ThemeContext;

  componentDidMount() {
    console.log("Current theme:", this.context);
  }

  render() {
    const theme = this.context as string;
    return <h1>Theme: {theme}</h1>;
  }
}

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

Try this example on CodeSandbox

↥ back to top

Q. How to update React Context from inside a child component?

The Context API allows data storage and makes it accessible to any child component who want to use it. This is valid whatever level of component graph the children is in.

Example:

/**
 * React Context API
 */
import { useState, useContext, createContext, useMemo, useCallback } from "react";

interface MyContextType {
  count: number;
  increment: () => void;
}

const MyContext = createContext<MyContextType | undefined>(undefined);

/**
 * Child Component
 */
const ChildComponent = () => {
  const { count, increment } = useContext(MyContext) as MyContextType;

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

/**
 * App Component
 * 
 * Root component that manages count state and provides it via MyContext.
 * Uses useMemo to memoize the context value and useCallback to stabilize
 * the increment handler, preventing unnecessary re-renders in consumers.
 */
export default function App() {
  const [count, setCount] = useState(0);
  
  const increment = useCallback(() => {
    setCount(prev => prev + 1);
  }, []);

  const contextValue = useMemo(() => ({ count, increment }), [count, increment]);

  return (
    <MyContext.Provider value={contextValue}>
        <ChildComponent />
    </MyContext.Provider>
  );
}

Here, the state is managed in the parent component alongside an updater function that modifies it. Both the state value and the updater function are passed as the context value via the Provider. Any child component can then consume this context, call the updater function, and trigger a state change in the parent — effectively updating the shared context.

Try this example on CodeSandbox

↥ back to top

Q. What is prop drilling and how can you avoid it?

Prop drilling is when data is passed through multiple intermediate component layers via props just to reach a deeply nested child that needs it — even though the components in between don't use that data themselves.

Why it's a problem:

Using Context API:

The Context API solves some of these prop drilling problems. It let pass data to all of the components in the tree without writing them manually in each of them. Shared data can be anything: state, functions, objects, we name it, and it is accessible to all nested levels that are in the scope of the context.

Example:

/**
 * React Context API
 * 
 * Demonstrates sharing a value across the component tree without prop drilling.
 * NumberContext provides a numeric value to all descendant consumers.
 */
import { useContext, createContext } from "react";

// It returns an object with 2 values:
// { Provider, Consumer }
const NumberContext = createContext<number>(0);
const CONTEXT_VALUE = 100;

function Display() {
  const value = useContext(NumberContext);
  return <h3>Context Value: {value}</h3>;
}

/**
 * App Component
 * 
 * Wraps the component tree with NumberContext.Provider,
 * making CONTEXT_VALUE available to all children via useContext.
 */
export default function App() {
  return (
    <NumberContext.Provider value={CONTEXT_VALUE}>
        <Display />
    </NumberContext.Provider>
  );
}

Try this example on CodeSandbox

↥ back to top

# 13. REACT ROUTER


Q. What is React Router?

React router enables the navigation among views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL. It has a simple API with powerful features like lazy loading, dynamic route matching, and location transition handling.

Core components (v7):

Example:

/**
 * React Router v7
 */
import { BrowserRouter, Route, Routes, NavLink } from "react-router-dom";

/**
 * Home Component
 */
const Home = () => {
  return <h1>Home Page</h1>;
};

/**
 * Contacts Component
 */
const Contacts = () => {
  return <h1>Contact Page</h1>;
};

/**
 * App Component
 */
export default function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <div className="navbar">
          <NavLink to={"/"}>Home</NavLink>
          <NavLink to={"/contact"}>Contact Us</NavLink>
        </div>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/contact" element={<Contacts />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. What are the components of react router?

The main components of React router are

1. BrowserRouter:

BrowserRouter is a router implementation that uses the HTML5 history API (pushState, replaceState and popstate event) to keep your UI in sync with the URL. It is the parent component that is used to store all of the other components.

2. Routes:

It's a new component introduced in the v6 and a upgrade of the component. The main advantages of Routes over Switch that routes are chosen based on the best match instead of being traversed in order.

3. Route:

Route is the conditionally shown component that renders some UI when its path matches the current URL.

4. Link:

Link component is used to create links to different routes and implement navigation around the application. It works like HTML anchor tag.

5. NavLink:

Adds active styling to the link when its route matches the current URL

6. Outlet:

A critical component for nested routing. It acts as a placeholder within a parent route's component, indicating where child route elements should be rendered.

↥ back to top

The <Link> component is used to navigate the different routes on the site. But <NavLink> is used to add the style attributes to the active routes.

Link:

Renders an anchor tag that navigates without a full page reload. No awareness of whether the route is currently active.

<Link to="/">Home</Link>

NavLink:

Same as Link, but automatically applies an active CSS class (or custom class) when the to path matches the current URL.

<NavLink to="/" activeClassName="active">Home</NavLink>

Example:

index.css

.active {
  color: blue;
}

Routes.js

import { BrowserRouter as Router, Routes, Route, NavLink } from 'react-router-dom'
import './index.css'
import App from './App'
import Users from './users'
import Contact from './contact'
import Notfound from './notfound'

const nav = ({ isActive }) => isActive ? 'active' : undefined

const AppRoutes = () => (
  <Router>
    <div>
      <ul>
        <li><NavLink className={nav} to="/">Home</NavLink></li>
        <li><NavLink className={nav} to="/users">Users</NavLink></li>
        <li><NavLink className={nav} to="/contact">Contact</NavLink></li>
      </ul>
      <hr />
      <Routes>
        <Route path="/" element={<App />} />
        <Route path="/users" element={<Users />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="*" element={<Notfound />} />
      </Routes>
    </div>
  </Router>
)

export default AppRoutes;

Note:

In React Router v7, NavLink uses a function for className instead of activeClassName.

↥ back to top

Q. How React Router is different from history library?

React Router is a high-level, React-specific routing library built on top of the low-level history library. While the history library handles raw browser history manipulation, React Router adds declarative routing, component rendering, and React hooks on top of it.

Key Differences:

Feature history library React Router v7
Level Low-level High-level
React awareness None React-specific
Navigation history.push('/path') useNavigate() hook
Location access history.location useLocation() hook
URL params Manual useParams() hook
UI sync Manual Automatic

React Router v7 internalizes the history dependency — you no longer install or interact with it directly. All navigation is handled through hooks.

// <BrowserRouter> — clean URLs using HTML5 History API
http://example.com/about

// <HashRouter> — hash-based URLs for static hosting / legacy browsers
http://example.com/#/about

The <BrowserRouter> is preferred for modern apps as it uses the HTML5 History API. Use <HashRouter> only when you cannot configure the server to handle all routes (e.g., static file hosting).

Example (React Router v7):

// src/index.js
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

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

Navigating programmatically in v7:

import { useNavigate, useLocation } from "react-router-dom";

function MyComponent() {
  const navigate = useNavigate();   // replaces history.push / history.replace
  const location = useLocation();   // replaces history.location

  return (
    <button onClick={() => navigate("/home")}>Go Home</button>
  );
}

In React Router v7, history.goBack() and history.goForward() are replaced by navigate(-1) and navigate(1) respectively.

↥ back to top

Q. How to use useNavigate() in React Router v7?

The useNavigate() hook is introduced in React Router v7 to replace the useHistory() hook. In the earlier version, the useHistory() hook accesses the React Router history object and navigates to the other routers using the push() or replace() methods.

The useNavigate() hook returns a function that lets you navigate programmatically, for example after a form is submitted. If using replace: true, the navigation will replace the current entry in the history stack instead of adding a new one.

Example:

/**
 * useNavigate()
 */
import { useNavigate } from "react-router-dom";

function Home() {
  const navigate = useNavigate();

  return (
    <button onClick={() => navigate("/profile")}>
      Go to Profile
    </button>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to get parameter value from query string in React?

1. useSearchParams:

The useSearchParams hook is a feature provided by libraries such as React Router and Next.js that allows React components to read and update the query string parameters (the portion of the URL after the ? symbol).

This hook is essential for managing URL-based state, which keeps the application's state persistent when the page is reloaded or the link is shared

Usage:

Example:

// http://localhost:3000/search?q=react

import { useSearchParams } from "react-router-dom";

function SearchPage() {
  const [searchParams] = useSearchParams();
  
  // Get a specific parameter by its key
  const query = searchParams.get("q"); // URL: /search?q=react

  return <div>Search results for: {query}</div>;
}

2. useParams:

useParams is a React Router hook used to extract dynamic parameters from the current URL path. These parameters are defined in your route configuration using a colon (:) followed by a variable name.

Example:

// http://localhost:3000/:userId

import { useParams } from "react-router-dom";

function Profile() {
  // Extract userId from the URL path
  const { userId } = useParams();

  return <h1>Viewing profile for user: {userId}</h1>;
}

Try this example on CodeSandbox

↥ back to top

Q. How to access history object in React Router v7?

The useNavigate() hook has been added to React Router v7 to replace the useHistory() hook.

Difference:

v5 (useHistory) v7 (useNavigate)
history.push('/path') navigate('/path')
history.replace('/path') navigate('/path', { replace: true })
history.goBack() navigate(-1)
history.goForward() navigate(1)

Example:

/**
 * React Router
 */
import { BrowserRouter, Routes, NavLink, Route, useParams, useNavigate } from "react-router-dom";

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <ul>
          <li><NavLink to="/">Home</NavLink></li>
          <li><NavLink to="/user/Bhavya/bhavyasingh@email.com">User Profile</NavLink></li>
        </ul>
        <Routes>
          <Route path="/user/:name/:email" element={<User />} />
          <Route path="/" element={<Home />} />
        </Routes>
        <HomeButton />
      </div>
    </BrowserRouter>
  );
}

function Home() {
  return <h2>Welcome Home</h2>;
}

function User() {
  let { name, email } = useParams();
  return (
    <h2>Name: {name} <br /> Email: {email}</h2>
  );
}

function HomeButton() {
  const navigate = useNavigate();

  function handleClick() {
    navigate("/");
  }

  return (
    <>
      <button type="button" onClick={handleClick}>Go Home</button>
    </>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to perform automatic redirect in React.js?

In contrast to the Navigate component and its declarative redirect, we can perform a programmatic redirect by using React Router's useNavigate() Hook:

Example: Using <Navigate> component (declarative)

/**
 * Automatic Redirect in React Router v7
 */
import {
  BrowserRouter,
  Routes,
  Route,
  Navigate,
  NavLink,
} from "react-router-dom";

// --- Approach 1: <Navigate> component (declarative) ------------------------------

function AppWithNavigate() {
  return (
    <BrowserRouter>
      <nav style=>
        <NavLink to="/home">Home</NavLink>
        <NavLink to="/about">About</NavLink>
        <NavLink to="/help">Help</NavLink>
      </nav>
      <Routes>
        {/* Visiting "/" automatically redirects to "/home" */}
        <Route index element={<Navigate replace to="/home" />} />
        <Route path="home" element={<h1>Home Page</h1>} />
        <Route path="about" element={<h1>About Page</h1>} />
        <Route path="help" element={<h1>Help Page</h1>} />
      </Routes>
    </BrowserRouter>
  );
}
export default AppWithNavigate;

Example: Using redirect() in a loader (v7 data router)

// --- Approach 2: redirect() in a loader (v7 data router) ---------------------

import { createBrowserRouter, RouterProvider, redirect } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    // loader runs before rendering; returning redirect() sends the user elsewhere
    loader: () => redirect("/home"),
  },
  {
    path: "/home",
    element: <h1>Home Page</h1>,
  },
  {
    path: "/about",
    element: <h1>About Page</h1>,
  },
]);

function AppWithLoaderRedirect() {
  return <RouterProvider router={router} />;
}
export default AppWithLoaderRedirect;

Note:

To keep the history clean, you should set replace prop. This will avoid extra redirects after the user click back.

Try this example on CodeSandbox

↥ back to top

Q. How to pass additional data while redirecting to a route in React?

Using Link:

Example:

/**
 * Pass additional data while redirecting
 */
import { BrowserRouter, Link, Route, Routes, useLocation } from "react-router-dom";

/**
 * View User Component
 */
function ViewUser() {
  const location = useLocation();
  return (
    <>
      <h2>User Details</h2>
      <div>Name:{location.state.name}</div>
      <div>Email:{location.state.email}</div>
    </>
  );
}

/**
 * User Component
 */
function User() {
  return (
    <div>
      <h2>Pass additional data while redirecting</h2>
      <Link
        to="/view-user"
        state=
      >
        <button>View User</button>
      </Link>
    </div>
  );
}

/**
 * App Component
 */
export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route exact path="/" element={<User />} />
        <Route exact path="/user" element={<User />} />
        <Route exact path="/view-user" element={<ViewUser />} />
      </Routes>
    </BrowserRouter>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. How to pass props in React router v7?

React Router uses a declarative, component-based approach to routing. Route allows you to map URL paths to different React components.

Example:

/**
 * pass props directly via the element prop
 */
import { BrowserRouter, Routes, Route, NavLink } from "react-router-dom";

export function Greeting(props) {
  const { text } = props;
  return (
    <>
      <h2>Greetings Page</h2>
      <p>{text}</p>
    </>
  );
}

const RouterExample = () => <h2>Home Page</h2>;

const App = () => (
  <BrowserRouter>
    <ul>
      <li><NavLink to="/">Home</NavLink></li>
      <li><NavLink to="/greeting/pradeep">Greeting</NavLink></li>
    </ul>
    <hr />
    <Routes>
      <Route exact path="/" element={<RouterExample />} />
      <Route path="/greeting/:name" element={<Greeting text="Hello World" />} />
    </Routes>
  </BrowserRouter>
);

export default App;

Try this example on CodeSandbox

↥ back to top

Q. How to get query parameters in react routing?

1. useParams() — for dynamic path segments

Used when the parameter is part of the URL path, defined with : in the route.

2. useSearchParams() — for query string parameters

Used when the parameter is in the query string (after ?).

Example:

/**
 * useParams()
 */
import { BrowserRouter, Route, Routes, Link, useParams } from "react-router-dom";

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <ul>
          <li><Link to="/home">Home</Link></li>
          <li><Link to="/contact-us">Contact Us</Link></li>
          <li><Link to="/help">Help</Link></li>
        </ul>
        <Routes>
          <Route path="/:id" element={<Child />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

function Child() {
  // `useParams` hook used here to access parameters
  let { id } = useParams();

  return <h2>Parameter: {id}</h2>;
}

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between HashRouter and BrowserRouter in React?

1. BrowserRouter:

Syntax:

/**
 * https://example.com/home
 * https://example.com/about
 */
<BrowserRouter
  basename={optionalString}
  forceRefresh={optionalBool}
  getUserConfirmation={optionalFunc}
  keyLength={optionalNumber}
>
  <App />
</BrowserRouter>

Example:

/**
 * BrowserRouter()
 */
import { Link, BrowserRouter, Routes, Route } from "react-router-dom";

const HomePage = () => {
  return <h2>Home Page</h2>;
};

const AboutPage = () => {
  return <h2>About Page</h2>;
};

export default function App() {
  return (
    <section className="App">
      <BrowserRouter>
        <ul>
          <li><Link to="/home">Home</Link></li>
          <li><Link to="/about">About</Link></li>
        </ul>
        <Routes>
          <Route exact path="/home" element={<HomePage />} />
          <Route exact path="/about" element={<AboutPage />} />
        </Routes>
      </BrowserRouter>
    </section>
  );
}

Try this example on CodeSandbox

2. HashRouter:

Syntax:

/**
 * https://example.com/#/home
 * https://example.com/#/about
 */
<HashRouter
  basename={optionalString}
  getUserConfirmation={optionalFunc}
  hashType={optionalString}
>
  <App />
</HashRouter>

Example:

/**
 * HashRouter()
 */
import { Link, HashRouter, Routes, Route } from "react-router-dom";

const HomePage = () => {
  return <h2>Home Page</h2>;
};

const AboutPage = () => {
  return <h2>About Page</h2>;
};

export default function App() {
  return (
    <section className="App">
      <HashRouter>
        <ul>
          <li><Link to="/home">Home</Link></li>
          <li><Link to="/about">About</Link></li>
        </ul>
        <Routes>
          <Route exact path="/home" element={<HomePage />} />
          <Route exact path="/about" element={<AboutPage />} />
        </Routes>
      </HashRouter>
    </section>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. What is route based code splitting?

Route based code splitting is essential during the page transitions on the web, which takes some amount of time to load. Here is an example of how to setup route-based code splitting into the app using React Router with React.lazy.

Key Benefits

Example:

/**
 * Lazy Loading
 */
import React, { Suspense, lazy } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

const Home = lazy(() => import("./Home"));
const About = lazy(() => import("./About"));

export default function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route exact path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. What is lazy function in React?

React.lazy() makes it easy to create components that are loaded using dynamic import() but are rendered like regular components. This will automatically cause the bundle containing the component to be loaded when the component is rendered.

React.lazy() takes a function as its argument that must return a promise by calling import() to load the component. The returned Promise resolves to a module with a default export containing the React component.

Example:

import React, { lazy } from 'react'

const MyComponent = React.lazy(() => import('./MyComponent'))

const App = () => {
  <div>
    <MyComponent />
  </div>
}
↥ back to top

Q. What is code-splitting?

Code-Splitting is a feature supported by bundlers like Webpack, Rollup and Browserify ( via factor-bundle ) which can create multiple bundles that can be dynamically loaded at runtime.

Code splitting uses React.lazy and Suspense library, which helps to load a dependency lazily and only load it when needed by the user. The code splitting improves:

React.lazy and Suspense:

The React.lazy function allows us to render a dynamic import as a regular component. The suspense component is responsible for handling the output when the lazy component is fetched and rendered.

Example:

import React, { Suspense } from 'react';

const UsersComponent = React.lazy(() => import('./UsersComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <UsersComponent />
      </Suspense>
    </div>
  );
}
↥ back to top

Q. What is dynamic import in react?

React.lazy() wraps a dynamic import() call. The import returns a Promise that resolves to a module with a default export of a React component. The lazy component must be rendered inside <Suspense> to show a fallback while loading.

Example:

import React, { Suspense } from 'react';

const UsersComponent = React.lazy(() => import('./UsersComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <UsersComponent />
      </Suspense>
    </div>
  );
}
↥ back to top

Q. What are loadable components?

If you want to do code-splitting in a server rendered app, it is recommend to use Loadable Components because React.lazy and Suspense is not available for server-side rendering (SSR). Loadable lets you render a dynamic import as a regular component.

Installation:

npm install @loadable/component

Key Features

Example:

import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import loadable from '@loadable/component'

// 1. Define your loadable components
// The fallback prop shows a UI while the component is downloading
const Home = loadable(() => import('./routes/Home'), {
  fallback: <div>Loading Home...</div>,
})

const Dashboard = loadable(() => import('./routes/Dashboard'), {
  fallback: <div>Loading Dashboard...</div>,
})

const App = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route path="/dashboard" component={Dashboard} />
    </Switch>
  </Router>
)

export default App
↥ back to top

# 14. REACT ERROR BOUNDARIES


Q. What are error boundaries in React?

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

Key methods:

Syntax:

<ErrorBoundary>
   <User/>
</ErrorBoundary>

Example:

/**
 * ErrorBoundary Component
 *
 * Note: Error boundaries only catch errors during rendering, in lifecycle
 * methods, and in constructors of the whole tree below them. They do NOT
 * catch errors inside event handlers.
 */
import React from "react";

class ErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean }
> {
  constructor(props: { children: React.ReactNode }) {
    super(props);
    this.state = { hasError: false };
  }

  // Updates state so the next render shows the fallback UI
  static getDerivedStateFromError() {
    return { hasError: true };
  }

  // Used for logging error information
  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

function MyComponent() {
  return <p>Hello from MyComponent</p>;
}

// Usage: Wrap components that might crash during render
export default function App() {
  return (
    <ErrorBoundary>
      <MyComponent />
    </ErrorBoundary>
  );
}

Here, We have a state object having two variables isErrorOccured and errorMessage which will be updated to true if any error occurs.

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between try catch block and error boundaries?

1. Try…catch is used in specific code blocks where you program the functionality of the application.

/**
 * Try…catch
 */
import { useState } from 'react';

function Profile() {
  const [error, setError] = useState<string | null>(null);

  const handleUpdate = async () => {
    try {
      // Imperative logic: Step-by-step actions
      const response = await fetch('/api/update-profile');
      if (!response.ok) throw new Error('Update failed');
      // ... process data
    } catch (err) {
      // Manually handle the error state for the UI
      setError(err instanceof Error ? err.message : 'An unknown error occurred');
    }
  };

  return (
    <div>
      {error && <p>Error: {error}!</p>}
      <button onClick={handleUpdate}>Update Profile</button>
    </div>
  );
}
export default Profile;

2. Error Boundaries deal with declarative code. Imperative programming is how you do something and declarative programming is what you do.

With error boundary, if there is an error, you can trigger a fallback UI; whereas, with try…catch, you can catch errors in your code.

import ErrorBoundary from "error-boundary";

function Users() {
  return (
    <div>
      <ErrorBoundary>
        <Users />
      </ErrorBoundary>
    </div>
  )
}

Differences:

In React, the primary difference is that Error Boundaries are for declarative code (the UI structure), while try-catch is for imperative code (logical steps or actions). If there's an error, Error Boundaries trigger a fallback UI for the entire component subtree, whereas try...catch catches errors within specific code execution paths.

Note:

Error Boundaries cannot catch errors in event handlers — you must use try...catch for those.

Try this example on CodeSandbox

↥ back to top

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

Component Stack Trace prints all errors that occurred during rendering to the console in development, even if the application accidentally swallows them. It also display the filenames and line numbers in the component stack trace.

Example:

Component Stack Trace

↥ back to top

Q. What are the methods invoked during error handling?

To create an error boundary, we simply have to create a class component and define a state variable for determining whether the error boundary has caught an error. Our class component should also have at least three methods:

Example:

/**
 * Error Boundary in React
 */
import React from 'react';

class ErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean }
> {
  constructor(props: { children: React.ReactNode }) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(): { hasError: boolean } {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    // Log the error to an error reporting service
    console.error(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;
↥ back to top

# 15. REACT REFS


Q. What do you understand by refs in React?

The Refs (short for “references”) provide a way to access DOM without triggering a component re-render. React Refs are a useful feature that act as a means to reference a DOM element or a class component from within a parent component.

Refs also provide some flexibility for referencing elements within a child component from a parent component, in the form of ref forwarding.

Example:

/**
 * Refs
 */
import { useRef, useState } from "react";

function App() {
  // create a ref to store the textInput DOM element
  const textInput = useRef<HTMLInputElement>(null);
  const [value, setValue] = useState('');

  // Set the state for the ref
  const handleSubmit = (e: React.SubmitEvent<HTMLFormElement>) => {
    e.preventDefault();
    setValue(textInput.current?.value ?? '');
  };

  return (
    <div>
      <h1>React Ref - useRef Example</h1>
      <h3>Value: {value}</h3>
      <form onSubmit={handleSubmit}>
        {/** Call the ref on <input> so we can use it to update the <h3> value **/}
        <input type="text" ref={textInput} />
        <button>Submit</button>
      </form>
    </div>
  );
}

export default App;

When to Use Refs:

When not to use refs:

↥ back to top

Q. How can I use multiple refs for an array of elements with hooks?

To manage multiple refs for an array of elements, use a single useRef initialized to an empty array, then populate it via callback refs in your .map():

Example:

/**
 * Multiple Refs
 */
import { useRef } from 'react';

function MyComponent() {
  const items = [10, 20, 30];
  const itemRefs = useRef<(HTMLLIElement | null)[]>([]);

  return (
    <ul>
      {items.map((item, index) => (
        <li 
          key={item} 
          ref={el => { itemRefs.current[index] = el; }}
        >
          {item}
        </li>
      ))}
    </ul>
  );
}

export default MyComponent; 

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between useRef() and createRef()?

1. useRef():

The useRef is a hook that uses the same ref throughout. It saves its value between re-renders in a functional component and doesn't create a new instance of the ref for every re-render. It persists the existing ref between re-renders.

Example:

/**
 * useRef()
 */
import { useEffect, useRef, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const ref = useRef<number | null>(null);

  useEffect(() => {
    ref.current = 100; // Initial Value
  }, []);

  useEffect(() => {
    console.log(count, ref.current);
  }, [count]);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 10)}>Increment</button>
      <p>{count}</p>
    </div>
  );
}

Try this example on CodeSandbox

2. createRef():

The createRef is a function that creates a new ref every time. Unlike the useRef, it does not save its value between re-renders, instead creates a new instance of the ref for every re-render. Thus implying that it does not persist the existing ref between re-renders.

Example:

/**
 * createRef()
 */
import React, { createRef } from "react";

type AppProps = Record<string, never>;
type AppState = { count: number };

export default class App extends React.Component<AppProps, AppState> {
  ref = createRef<number>();

  constructor(props: AppProps) {
    super(props);
    this.state = { count: 0 };
  }

  componentDidMount() {
    this.ref.current = 100; // Initial Value
  }

  componentDidUpdate(prevProps: AppProps, prevState: AppState) {
    if (prevState.count !== this.state.count) {
      console.log(this.state.count, this.ref.current);
    }
  }

  render() {
    return (
      <div className="App">
        <button onClick={() => this.setState((s) => ({ count: s.count + 10 }))}>
          Increment
        </button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}

Note:

Always use useRef() in functional components. createRef() is intended for class components where it's called once in the constructor. In classes, you typically call it once in the constructor and assign it to this.myRef. Because the class instance stays the same during re-renders, the ref remains stable.

Try this example on CodeSandbox

↥ back to top

Inline ref callbacks are not recommended because they get called twice on every update:

This happens because a new function instance is created on every render, so React treats it as a different ref each time and must clean up the old one before assigning the new one.

Example: The Problem: Inline Ref Callbacks

/**
 * Inline Ref Callback()
 */
import { useState } from 'react';

function InlineRefExample() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <input 
        ref={(node) => {
          // This logs TWICE on every re-render: 
          // 1. "Ref is null" (cleanup)
          // 2. "Ref is [object HTMLInputElement]" (setup)
          console.log("Ref is:", node); 
        }} 
      />
      <button onClick={() => setCount(c => c + 1)}>Re-render ({count})</button>
    </div>
  );
}

Example: The Solution: useCallback Ref

import { useState, useCallback } from 'react';

function StableRefExample() {
  const [count, setCount] = useState(0);

  // Memoize the function so it does not change on re-renders
  const stableRef = useCallback((node) => {
    if (node !== null) {
      console.log("Ref initialized once:", node);
    }
  }, []); // Empty deps means it never changes

  return (
    <div>
      <input ref={stableRef} />
      <button onClick={() => setCount(c => c + 1)}>Re-render ({count})</button>
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. Which is the preferred option callback refs or findDOMNode()?

Callback refs are the preferred option over findDOMNode() in React.

While findDOMNode() was once a common way to access an element's underlying DOM node, it is now discouraged and deprecated in Strict Mode. In modern React, you should use refs (either via useRef for functional components or createRef/callback refs for class components)

Example: The legacy approach of using findDOMNode()

class MyComponent extends Component {
  componentDidMount() {
    findDOMNode(this).scrollIntoView()
  }

  render() {
    return <div />
  }
}

Example: The recommended approach is useRef

import { useRef, useEffect } from 'react';

function MyComponent() {
  const nodeRef = useRef(null);

  useEffect(() => {
    nodeRef.current.scrollIntoView();
  }, []);

  return <div ref={nodeRef} />;
}
↥ back to top

Q. How to set focus on an input field after rendering?

Use useRef to get a reference to the input element and useEffect with an empty dependency array to call .focus() once after the component mounts.

Example:

import { useRef, useEffect } from 'react';

function AutoFocusTextInput() {
  const textInput = useRef(null);

  useEffect(() => {
    textInput.current.focus();
  }, []);

  return <input ref={textInput} />;
}
↥ back to top

Q. Why are string refs considered legacy in React?

Although string refs are not deprecated, they are considered legacy, and will likely be deprecated at some point in the future. Callback refs are preferred.

Callback Refs:

Instead of passing a ref attribute created by createRef(), you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere.

Example: Legacy String Ref (Deprecated)

// LEGACY: Do not use this in modern React
class LegacyComponent extends React.Component {
  componentDidMount() {
    // Accessing the element via the string name
    this.refs.myInput.focus();
  }

  render() {
    return <input ref="myInput" />;
  }
}

Example: Modern useRef Hook (Recommended)

// MODERN: The standard approach
import { useRef } from 'react';

function ModernComponent() {
  const inputRef = useRef(null);

  const handleClick = () => {
    // Accessing the DOM element via .current
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>Focus Input</button>
    </>
  );
}

Example: Modern Callback Ref

// ADVANCED: Useful for dynamic elements
function CallbackRefExample() {
  const setRef = (node) => {
    if (node) {
      console.log("Input is mounted:", node);
      node.focus();
    } else {
      console.log("Input is unmounted");
    }
  };

  return <input ref={setRef} />;
}

Try this example on CodeSandbox

↥ back to top

Q. What is forwardRef() in React?

Ref forwarding is a technique for passing a ref through a component to one of its children. It is very useful for cases like reusable component libraries and Higher Order Components (HOC).

We can forward a ref to a component by using the React.forwardRef() function. Ref forwarding allows components to take a ref they receive and pass it further down (in other words, “forward” it) to a child.

Example:

// Child component wraps itself with forwardRef
const TextInput = React.forwardRef((props, ref) => (
  <input type="text" ref={ref} />
));

// Parent creates a ref and passes it to the child
function Parent() {
  const inputRef = React.createRef();

  const handleClick = () => {
    inputRef.current.focus(); // directly accesses the <input> DOM node
  };

  return (
    <>
      <TextInput ref={inputRef} />
      <button onClick={handleClick}>Focus</button>
    </>
  );
}

In the example above, we have a component called TextInput that has a child which is an input field. First, we start by creating a ref with the line of code below:

const inputRef = React.createRef()

We pass our ref down to <TextInput ref={inputRef}> by specifying it as a JSX attribute. React then forwards the ref to the forwardRef() function as a second argument. Next, We forward this ref argument down to <input ref={ref}>. The value of the DOM node can now be accessed at inputRef.current.

Common use cases:

↥ back to top

Q. How to debug forwardRefs() in DevTools?

React.forwardRef accepts a render function as parameter and DevTools uses this function to determine what to display for the ref forwarding component.

Problem: If you don't name the render function or not using displayName property then it will appear as “ForwardRef” in the DevTools,

const WrappedComponent = React.forwardRef((props, ref) => {
  return <LogProps {...props} forwardedRef={ref} />;
});

Solution: If you name the render function then it will appear as “ForwardRef(myFunction)”

/**
 * set displayName explicitly
 */
const WrappedComponent = React.forwardRef((props, ref) => {
  return <LogProps {...props} forwardedRef={ref} />;
});

WrappedComponent.displayName = 'myFunction';
// DevTools shows: ForwardRef(myFunction)

Example:

const ForwardP = React.forwardRef(function ForwardP(props, ref) {
  return (
    <>
      <p>I'm a real component too</p>
      <p>
        Especially with <code>useImperativeMethods</code>
      </p>
      <p {...props} ref={ref} />
    </>
  );
});

function App() {
  return (
    <div className="App">
      <ForwardP style=>
        But my props are <code>null</code> in DevTools
      </ForwardP>
    </div>
  );
}

forwardRef()

Try this example on CodeSandbox

↥ back to top

Q. What is difference between useRef() and useState() in React?

Both useRef() and useState() are React hooks for managing data, but they serve different purposes and behave differently. useState triggers a re-render when updated; useRef does not.

Key Differences:

Feature useRef() useState()
Purpose Store mutable values that persist Manage component state
Re-render Does NOT trigger re-render Triggers re-render
Update Synchronous Asynchronous
Access .current property Direct value
Common Use DOM references, timers UI state, user input

useState(): for values that drive the UI

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1); // Triggers re-render
    console.log(count); // May show old value (async)
  };

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}

useRef(): for values that don't need to update the UI

import React, { useRef } from 'react';

function Counter() {
  const countRef = useRef(0);

  const handleClick = () => {
    countRef.current += 1; // Does NOT trigger re-render
    console.log(countRef.current); // Shows updated value immediately
  };

  return (
    <div>
      <h2>Count: {countRef.current}</h2> {/* Won\'t update on screen */}
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}

Common Use Cases:

1. useRef for DOM Access:

function TextInput() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

2. useRef for Storing Previous Values:

function Component() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  useEffect(() => {
    prevCountRef.current = count;
  }, [count]);

  return (
    <div>
      <h2>Current: {count}</h2>
      <h2>Previous: {prevCountRef.current}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

3. useRef for Timers:

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef(null);

  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };

  return (
    <div>
      <h2>{seconds} seconds</h2>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

Use useState when:

Use useRef when:

Note:

↥ back to top

# 16. REACT COMPOSITION


Q. Explain Inheritance in React?

In React, inheritance is a concept where one component inherits properties or behaviors from another, typically using the extends keyword in Class Components. However, it is considered an anti-pattern and is officially discouraged by the React team. The React team recommends Composition over Inheritance.

Example:

/**
 * Parent Class
 */
import React from "react";

export class ParentClass extends React.Component {
  constructor(props) {
    super(props);
    this.callMe = this.callMe.bind(this);
  }

  // ParentClass function
  callMe() {
    console.log("This is a method from parent class");
  }

  render() {
    return false;
  }
}
/**
 * Child Class
 */
export default class App extends ParentClass {
  render() {
    return <button onClick={() => this.callMe()}>Call Parent</button>;
  }
}

Try this example on CodeSandbox

Note:

React does not use inheritance except in the initial component class, which extends from the react package.

↥ back to top

Q. Explain Composition in React?

Composition is a pattern where components are built by combining smaller, reusable components together — rather than inheriting from a parent. It follows the “has-a” relationship (a component uses another component).

Benefits

Example: Basic Containment using children prop

/**
 * Composition in React
 */
// Card.jsx (a reusable wrapper component)
const Card = ({ children }) => (
  <div style=>
    {children}
  </div>
);

// App.jsx (composing content inside the Card)
function App() {
  return (
    <Card>
      <h2>Card Title</h2>
      <p>This is some content inside the card.</p>
    </Card>
  );
}

export default App;

Try this example on CodeSandbox

↥ back to top

Q. How Composition is different from Inheritance in React?

Inheritance used the is-a relationship method. Derived components had to inherit the properties of the base component and it was quite complicated while modifying the behavior of any component.

Composition does not inherit properties, only the behavior. In inheritance, it was difficult to add new behavior because the derived component was inheriting all the properties of parent class and it was quite difficult to add new behavior. But in composition, we only inherit behavior and adding new behavior is fairly simple and easy.

React recommends use of Composition over Inheritance, here is why. Everything in React is a component, and it follows a strong component based model. This is one of the primary reasons that composition is a better approach than inheritance for code reuse.

Composition vs Inheritance

  Inheritance Composition
Relationship is-a has-a
Coupling Tightly coupled Loosely coupled
Behavior reuse Inherits all parent properties Shares only needed behavior
Flexibility Rigid — hard to modify Flexible — easy to extend
React recommendation Anti-pattern Preferred
↥ back to top

# 17. REACT CSS STYLING


Q. How to use styles in React.js?

React Components can add styling in the following ways:

1. Inline Styles:

Inline styles are applied directly to elements using the style attribute. In React, this attribute accepts a JavaScript object rather than a string.

Example:

/**
 * Inline Styling
 */
class HeaderComponent extends React.Component {
  render() {
    return (
      <div>
        <h1 style=>Header Component Style!</h1>
        <p>Add a little style!</p>
      </div>
    );
  }
}

Try this example on CodeSandbox

2. Styled-Components (CSS-in-JS)

This popular library allows you to write actual CSS code directly inside your JavaScript files using tagged template literals.

Example:

/**
 * Styled Components
 */
import styled from 'styled-components';

const Wrapper = styled.div`
  color: white;
  background: black;
  &:hover { color: gold; }
`;

Try this example on CodeSandbox

3. CSS Stylesheet:

You can write your CSS styling in a separate file, just save the file with the .css file extension, and import it in your application.

Example:

/**  
 * App.css 
 */
body {
  background-color: #282c34;
  color: white;
  padding: 40px;
  font-family: Arial;
  text-align: center;
}
/**
 * CSS Stylesheet
 */
import './App.css';

class HeaderComponent extends React.Component {
  render() {
    return (
      <div>
        <h1>Header Component Style!</h1>
        <p>Add a little style!.</p>
      </div>
    );
  }
}

4. CSS Modules:

CSS Modules allow you to scope CSS locally to a specific component, preventing global naming conflicts.

Example:

import styles from './Button.module.css';

function Button() {
  return <button className={styles.error}>Click Me</button>;
}
↥ back to top

Q. How to conditionally apply CSS classes in React JS?

Example: Using ternary operator

import { useState } from 'react'

function App() {
  const [isRed, setIsRed] = useState(true)

  return <p style=>Example Text</p>
}

Example: Using Logical AND (&&)

import { useState } from 'react'

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false)

  return (
    <>
      <p className={`message ${isLoggedIn && 'active'}`}>
        {isLoggedIn ? 'Welcome back!' : 'Please log in.'}
      </p>
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? 'Logout' : 'Login'}
      </button>
    </>
  )
}

Try this example on CodeSandbox

↥ back to top

Q. How to combine multiple inline style objects?

Example: Using Spread operator

const box = {
    color: "green",
    fontSize: '23px'
}

const shadow = {
    background: "orange",
    boxShadow: "1px 1px 1px 1px #cccd"
}

export default function App(){
    return (
      <div style=>
         <h1>Hello React</h1>
      </div>
    )
}

Example: Using Object.assign()

import { useState } from 'react'

export default function App() {
  const [isActive, setIsActive] = useState(false)

  const baseStyle = {
    padding: '10px 20px',
    borderRadius: '4px',
    border: '1px solid #ccc',
    cursor: 'pointer'
  }

  const activeStyle = {
    background: 'blue',
    color: 'white',
    border: '1px solid blue'
  }

  const combinedStyle = Object.assign({}, baseStyle, isActive ? activeStyle : {})

  return (
    <div>
      <div style={combinedStyle} onClick={() => setIsActive(!isActive)}>
        {isActive ? 'Active' : 'Inactive'}
      </div>
    </div>
  )
}

Try this example on CodeSandbox

↥ back to top

Quick Comparison

Package Style Best For
Framer Motion Declarative General UI, gestures
React Spring Physics-based Natural motion
React Transition Group CSS-based Enter/exit transitions
React Move Data-driven Data visualizations
React Reveal Scroll-based Landing pages
↥ back to top

Q. What is the benefit of styles modules?

In React, the primary benefit of using CSS Modules is that it provides local scoping for styles by default. This solves the common problem of global namespace collisions where styles from one component accidentally overwrite styles in another.

Benefits of CSS modules:

↥ back to top

Q. What are styled components?

styled-components is a CSS-in-JS library that lets you write actual CSS inside JavaScript using tagged template literals.

The styled-components comes with a collection of helper methods, each corresponding to a DOM node for example <h1>, <header>, <button>, and SVG elements like line and path. The helper methods are called with a chunk of CSS, using an obscure JavaScript feature known as “tagged template literals”.

Key Features

Example:

import styled from 'styled-components';

// This creates a button component with specific styles
const StyledButton = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid #bf4f74;
  color: #bf4f74;
  padding: 0.25em 1em;
`;

// Use it like any other React component
render(<StyledButton>Click Me</StyledButton>);
↥ back to top

Q. How to use useSpring() for animation?

In the React Spring library, useSpring() is a custom hook used to create single-spring animations that move data from one state to another. Unlike traditional CSS animations that rely on fixed durations and easing curves, useSpring uses spring physics—such as tension, friction, and mass—to produce motion that feels natural and mimics the real world.

Basic Implementation:

The most common way to use useSpring is by passing an object with from (initial state) and to (target state) properties.

Example:

/**
 * useSpring()
 */
import { useSpring, animated } from '@react-spring/web';

function FadeIn() {
  const styles = useSpring({
    from: { opacity: 0 },
    to: { opacity: 1 },
  });

  return <animated.div style={styles}>I will fade in!</animated.div>;
}

2. Interactive Animations:

You can trigger animations based on state changes (like hovers or clicks) by passing conditional values directly into the hook.

Example:

const [clicked, setClicked] = useState(false);

const springs = useSpring({
  width: clicked ? '300px' : '100px',
  background: clicked ? 'blue' : 'red',
  config: { tension: 200, friction: 20 } // Adjust physics here
});

return (
  <animated.div 
    onClick={() => setClicked(!clicked)} 
    style={springs} 
  />
);
↥ back to top

Q. How do you apply vendor prefixes to inline styles in React?

React does not automatically apply vendor prefixes to inline styles. You must either add them manually as camelCased properties or use a third-party library to handle them at runtime.

Manual Prefixing

To apply prefixes manually, add them as separate properties in your style object using camelCase.

Example:

const myStyle = {
  transform: 'rotate(45deg)',
  WebkitTransform: 'rotate(45deg)', // Chrome, Safari, newer Opera
  msTransform: 'rotate(45deg)'      // Internet Explorer 9
};

return <div style={myStyle}>Hello World</div>;

Try this example on CodeSandbox

↥ back to top

Q. How to display style based on props value?

When using Styled Components, you can access props by passing a function into the tagged template literal. This is the most common way to handle dynamic styles in React.

1. Simple Ternary (Toggle):

import styled from 'styled-components'

const Button = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'}
  color: 'white'
`;

function MyPureComponent(props) {
  return (
    <div>
      <Button>Normal</Button>
      <Button primary>Primary</Button>
    </div>
  )
}

2. Multi-line Blocks (CSS Helper)

If you need to apply a whole block of CSS rules based on a prop, use the css helper from the library. This keeps the code clean and ensures syntax highlighting works.

import styled, { css } from 'styled-components';

const Alert = styled.div`
  padding: 10px;
  
  ${props => props.urgent && css`
    background: red;
    font-weight: bold;
    border: 2px solid darkred;
  `}
`;

// Usage
<Alert urgent>Emergency!</Alert>

3. Complex Mapping (The “Switch” Pattern)

If your component has multiple states (e.g., ‘success’, ‘warning’, ‘error’), use a mapping object to avoid long if/else chains.

const themeColors = {
  success: 'green',
  warning: 'orange',
  error: 'red'
};

const StatusBox = styled.div`
  background: ${props => themeColors[props.status] || 'gray'};
`;

// Usage
<StatusBox status="success">Task Complete</StatusBox>
↥ back to top

# 18. REACT INTERNATIONALIZATION


Q. How to translate your React app with react-i18next?

1. Install Dependencies:

npm install i18next react-i18next i18next-browser-languagedetector i18next-http-backend

2. Configure i18next:

Create a new file i18n.js beside your index.js containing following content:

/**
 * i18next Component
 */
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import HttpBackend from 'i18next-http-backend';

i18n
  .use(HttpBackend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    debug: true,
    interpolation: {
      escapeValue: false, // React already escapes by default
    },
    backend: {
      loadPath: '/locales//translation.json',
    }
  });

export default i18n;

3. Create Translation Files

Organize your translations in JSON files within the public/locales directory. For example:

4. Use in Components:

Use the useTranslation hook to access the translation function (t) and the i18n instance.

/**
 * useTranslation() in React
 */

import { useTranslation } from "react-i18next";

export default function App() {
  const { t, i18n } = useTranslation();

  const changeLanguage = (lng) => {
    i18n.changeLanguage(lng);
  };

  return (
    <>
      <h2>{t("Welcome")}</h2>
      <button onClick={() => changeLanguage("en")}>English</button>
      <button onClick={() => changeLanguage("fr")}>French</button>
    </>
  );
}

Try this example on CodeSandbox

Reference:

↥ back to top

# 19. REACT MISCELLANEOUS


Q. What is render hijacking in React?

In React, render hijacking is a technique where one component controls or modifies the render output of another component. It is most commonly achieved using Higher-Order Components (HOCs), specifically through a pattern called Inheritance Inversion.

In Render Highjacking we can:

Common Use Cases

Render hijacking is typically used for advanced cross-cutting concerns:

Example: Inheritance Inversion HOC

function withHijack(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      // Hijack the render output
      const elementsTree = super.render();
      
      // Modify the output (e.g., adding a style or changing props)
      if (elementsTree && elementsTree.type === 'div') {
        return React.cloneElement(elementsTree, { 
          style: { color: 'blue' } 
        });
      }
      
      return elementsTree;
    }
  };
}
↥ back to top

Q. What is windowing technique in react?

Windowing (also known as list virtualization) is a performance optimization technique that renders only the items currently visible in the user's viewport, plus a small buffer, rather than rendering an entire large dataset at once.

How It Works

Instead of mounting thousands of DOM nodes simultaneously—which can cause laggy scrolling and high memory usage—windowing calculates which elements should be visible based on the scroll position.

Popular Libraries:

Example: react-window

import React from 'react';
import { FixedSizeList as List } from 'react-window';

// 1. Define the Row component
// It receives 'index' (to fetch data) and 'style' (crucial for positioning)
const Row = ({ index, style }) => (
  <div style=>
    Item {index}
  </div>
);

const App = () => {
  return (
    // 2. Wrap the Row in a List component
    <List
      height={400}        // Visible height of the "window"
      width={300}         // Width of the list
      itemCount={10000}   // Total number of items in the dataset
      itemSize={50}       // Height of each individual row in pixels
    >
      {Row}
    </List>
  );
};

export default App;

Try this example on CodeSandbox

↥ back to top

Q. How to optimize React Performance?

Optimizing React performance generally falls into three categories: reducing the size of your code, minimizing unnecessary rendering, and managing heavy data efficiently.

1. Reduce Initial Load (Bundle Size)

Large JavaScript bundles are a major cause of slow “Time to Interactive” (TTI).

2. Prevent Unnecessary Re-renders

React re-renders a component whenever its parent renders or its state/props change. You can skip this work for components that haven't actually changed:

3. Handle Large Data & Interactions

↥ back to top

Q. What do you understand with the term polling in React?

Polling in React is a mechanism where the application repeatedly calls an API at regular intervals to check for updated data and refresh the UI accordingly.

How Polling works in React

React itself doesn't provide polling out of the box, so its implemented using:

There are two primary ways polling is implemented:

1. Short Polling

The client sends an HTTP request at a fixed interval (e.g., every 5 seconds) regardless of whether the data has actually changed.

2. Long Polling

The client sends a request, and the server holds the connection open until new data is available or a timeout occurs.

Example: Recommended Approach (TanStack Query)

Using a library like TanStack Query (formerly React Query) is better because it handles background refetching, caching, and loading states automatically.

import { useQuery } from '@tanstack/react-query';

function UserActivity() {
  const { data, isLoading } = useQuery({
    queryKey: ['activeUsers'],
    queryFn: () => fetch('/api/active-users').then(res => res.json()),
    // Polls every 3 seconds
    refetchInterval: 3000, 
    // Continues polling even when the tab is in the background
    refetchIntervalInBackground: true 
  });

  if (isLoading) return <div>Loading...</div>;
  return <div>Active Users: {data.count}</div>;
}
↥ back to top

Q. What are the drawbacks of MVW pattern?

MVW stands for Model-View-Whatever

In React.js, the MVW (Model-View-Whatever) pattern—which typically encompasses variations like MVC (Model-View-Controller) or MVVM (Model-View-ViewModel)—is often considered a “mismatch” for React's core philosophy.

Drawbacks as applications scale:

React's unidirectional data flow (actions → reducer → state → UI) and Redux's single immutable state tree were specifically designed to solve these MVW problems — making state changes predictable, traceable, and replayable.

↥ back to top

Q. How do you update render elements?

React Elements are immutable — once created, you cannot update their children or attributes directly. To update a rendered element, you must re-render with a new element.

Using useState + useEffect (Recommended approach):

In practice, managing periodic updates via setInterval inside a component using hooks is the idiomatic React way. State changes trigger re-renders automatically.

Example:

import { useState, useEffect } from "react";

function Clock() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const id = setInterval(() => setTime(new Date()), 1000);
    return () => clearInterval(id); // cleanup on unmount
  }, []);

  return <h2>Current Time: {time.toLocaleTimeString()}</h2>;
}

export default Clock;

React's diffing algorithm ensures only the changed part of the DOM (the time string) is updated on each re-render.

Try this example on CodeSandbox

↥ back to top

Q. What is the difference between rendering and mounting in ReactJS?

Mounting happens once — when React inserts a component into the DOM for the first time and builds the initial DOM nodes from the component's output.

Rendering happens every time React calls the component function (or render() method) to get instructions for what the DOM should look like. This occurs on mount and on every subsequent re-render.

Re-rendering is when an already-mounted component renders again due to a state or prop change — React calls the component again, diffs the new output against the previous one, and updates only what changed.

Example:

import { useState, useEffect } from "react";

/**
 * Message Component
 * Mounts when showMessage is true, unmounts when false.
 */
function Message({ name }) {
  // Runs once after this component is mounted into the DOM
  useEffect(() => {
    console.log("Message mounted");
    return () => console.log("Message unmounted"); // cleanup on unmount
  }, []);

  // Runs after every re-render when `name` prop changes
  useEffect(() => {
    console.log("Message re-rendered, name =", name);
  }, [name]);

  return <h2>{name}</h2>;
}

/**
 * App Component
 * Renders on every state change, but Message only mounts/unmounts
 * when showMessage toggles between true and false.
 */
export default function App() {
  const [showMessage, setShowMessage] = useState(false);
  const [name, setName] = useState("Hello React!");

  return (
    <div>
      <button onClick={() => setShowMessage(true)}>Show Message</button>
      <button onClick={() => setShowMessage(false)}>Hide Message</button>
      <button onClick={() => setName("Hello World!")}>Change Name</button>
      {showMessage && <Message name={name} />}
    </div>
  );
}

Try this example on CodeSandbox

↥ back to top

Q. What is Flow in react?

Type Checking:

Type checking means ensuring that the type of a property (variable, object, function, string) in a programming language is being used as it should be. It is the process of verifying and enforcing the constraints of types, and it can occur either at compile time or at runtime. It helps to detect and report errors.

Type checking can be divided into two: static type checking and dynamic type checking.

1. Static Type Checking:

Static type checking is used in static-typed languages where the type of the variable is known at the compile time. This means that the type of the variable must be declared beforehand. Static typing usually results in compiled code that executes more quickly because the compiler already knows the exact data types that are in use.

2. Dynamic type checking:

Dynamic type checking is used in dynamic-typed languages where the type is usually known at runtime. This means that the type of the variable doesn't need to be explicitly defined.

Flow:

Flow is a static type checker for JavaScript apps that aims to find and eliminate problems as you code. Designed by the Facebook team for JavaScript developers, it's a static type checker that catches common errors in your application before they run.

Integrating Flow:

# Create React App with Flowchecker
npx create-react-app flowchecker

# Add Dependency
npm install --save-dev flow-bin

The next thing to do is add Flow to the “scripts” section of your package.json so that Flow can be used in the terminal. In the package.json file, add the code snippet below.

 "scripts": {
      "flow": "flow",
    }

Finally, for the Flow setup, run any of the commands below:

npm run flow init

This will help to create a Flow configuration file that should be committed. The Flow config file helps to determine the files that Flow should work with and what should be ignored.

Flow vs PropTypes vs TypeScript

  Flow PropTypes TypeScript
Check time Compile time Runtime Compile time
Scope Entire codebase Props only Entire codebase
Recommended for Medium/large apps Small apps Large apps

Note:

React recommends using Flow or TypeScript over PropTypes for larger codebases, as they catch a broader class of bugs at compile time rather than at runtime.

↥ back to top

Q. What is the difference between Flow and PropTypes?

Flow is a static analysis tool which uses a superset of the language, allows to add type annotations to all of your code and catch an entire class of bugs at compile time.

PropTypes is a basic type checker which has been patched onto React. It can not check anything other than the types of the props being passed to a given component.

↥ back to top

Q. What is React Fiber?

React Fiber is the reimplemented reconciliation algorithm introduced in React 16. It replaced the old Stack Reconciler, which processed component trees synchronously in a single pass — blocking the main thread from handling animations, layouts, and gestures.

Core Goals of Fiber

What is a Fiber?

A fiber is a plain JavaScript object representing a unit of work for a component. At any time, a component has at most two fibers:

React Fiber performs reconciliation in two phases: Render and Commit

1. Lifecycle methods called during render phase:(Asynchronous)

2. Lifecycle methods called during commit phase:(Synchronous)

The render phase is asynchronous — this is why three lifecycle methods were marked UNSAFE_: their execution order is no longer guaranteed.

React Fiber uses requestIdleCallback() to schedule the low priority work and requestAnimationFrame() to schedule high priority work.

Problems with Current Implementation:

How React Fiber works:

Fiber is currently available for use but it runs in compatibility mode with the current implementation.

↥ back to top

Q. Does the static object work with ES6 classes in React?

Yes, Although statics only works with the legacy React.createClass(), you can still write static methods in ES6 notation. If you are using ES7, then you can also write static properties.

Example:

import React from 'react';
import PropTypes from 'prop-types';

class UserCard extends React.Component {
  // ES7 static property: type validation
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number,
    role: PropTypes.oneOf(['admin', 'user', 'guest'])
  };

  // ES7 static property: default values
  static defaultProps = {
    age: 0,
    role: 'user'
  };

  // ES6 static method: utility / factory helper
  static formatRole(role) {
    return role.charAt(0).toUpperCase() + role.slice(1);
  }

  render() {
    const { name, age, role } = this.props;
    return (
      <div>
        <h2>{name}</h2>
        <p>Age: {age}</p>
        <p>Role: {UserCard.formatRole(role)}</p>
      </div>
    );
  }
}

// Static methods can be called directly on the class (no instance needed)
console.log(UserCard.formatRole('admin')); // "Admin"

export default UserCard;
↥ back to top

Q. How do you access imperative API of web components?

Web Components often expose an imperative API (methods you call directly on the DOM element, like .play(), .focus(), .open()). Since React's declarative model does not directly call these, you need a ref to access the underlying DOM node.

Example: Using React in your Web Components

// 1. Define the Web Component (vanilla JS)
import { createRoot } from 'react-dom/client';

class XSearch extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement('span');
    this.attachShadow({ mode: 'open' }).appendChild(mountPoint);

    const name = this.getAttribute('name');
    const url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
    createRoot(mountPoint).render(<a href={url}>{name}</a>);
  }
}
customElements.define('x-search', XSearch);
// 2. Use the Web Component from a React Functional Component
import { useRef, useEffect } from 'react';

function SearchComponent({ name }) {
  const searchRef = useRef(null);

  useEffect(() => {
    if (searchRef.current) {
      // Access the web component's imperative API via the ref
      // e.g., searchRef.current.someMethod();
    }
  }, [name]);

  return (
    <div>
      Results: <x-search ref={searchRef} name={name}></x-search>!
    </div>
  );
}

export default SearchComponent;
↥ back to top

Q. What is the purpose of eslint plugin for hooks?

The ESLint plugin ( eslint-plugin-react-hooks ) enforces rules of Hooks to avoid bugs. It assumes that any function starting with “use” and a capital letter right after it is a Hook. In particular, the rule enforces that,

// ESLint configuration
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

Note:

This plugin is included by default in Create React App.

↥ back to top

Q. What is service worker in React.js?

A service worker is a background worker that acts as a programmable proxy, allowing us to control what happens on a request-by-request basis. We can use it to make (parts of, or even entire) React apps work offline.

Service workers depend on two APIs to work effectively: Fetch (a standard way to retrieve content from the network) and Cache (content storage for application data. This cache is independent from the browser cache or network status).

Service Worker Lifecycle:

Each service worker goes through three steps in its lifecycle: registration, installation and activation.

Service Worker Lifecycle

Registration:

To install a service worker, you need to register it in script. Registration informs the browser where your service worker is located and lets it know it can start installing in the background.

Example: Basic registration in your index.html could look like this

// Check for browser support of service worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('service-worker.js')

 .then(function(registration) {
   // Successful registration
   console.log('Registration successful, scope is:', registration.scope);

 }).catch(function(err) {
   // Failed registration, service worker won\'t be installed
   console.log('Service worker registration failed, error:', error);

 });
}

Installation and activation:

Service workers are event driven. The installation and activation processes fire off corresponding install and activate events to which the service workers can respond.

With the service worker registered, the first time a user hits your PWA, the install event will be triggered and this is where you'll want to cache the static assets for the page.

↥ back to top

Q. What is the purpose of registerServiceWorker in React?

React creates a service worker for you without any configuration by default. The service worker is a web API that helps you cache your assets and other files so that when the user is offline or on slow network, user can still see results on the screen.

Example: Enable service worker in react

/**
 * Register Service Worker
 */
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';

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

// Register the service worker for offline support and faster loads.
// Pass optional callbacks to handle lifecycle events:
serviceWorkerRegistration.register({
  onSuccess: (registration) => {
    console.log('Service Worker registered successfully:', registration.scope);
  },
  onUpdate: (registration) => {
    // Notify the user that a new version is available
    console.log('New content available; please refresh.', registration);
  },
});

// To opt out of service workers entirely, call unregister() instead:
serviceWorkerRegistration.unregister();
↥ back to top

Q. How Virtual-DOM is more efficient than Dirty checking?

Virtual DOM

React Virtual DOM:

In React, Each time the DOM updates or data of page changes, a new Virtual DOM representation of the user interface is made. It is just a lightweight copy or DOM.

Virtual DOM in React has almost same properties like a real DOM, but it can not directly change the content on the page. Working with Virtual DOM is faster as it does not update anything on the screen at the same time. In a simple way, Working with Virtual DOM is like working with a copy of real DOM nothing more than that.

Updating virtual DOM in ReactJS is faster because ReactJS uses

  1. It is efficient diff algorithm.
  2. It batched update operations
  3. It efficient update of sub tree only
  4. It uses observable instead of dirty checking to detect change

How Virtual DOM works in React:

When we render a JSX element, each virtual DOM updates. This approach updates everything very quickly. Once the Virtual DOM updates, React matches the virtual DOM with a virtual DOM copy that was taken just before the update. By Matching the new virtual DOM with pre-updated version, React calculates exactly which virtual DOM has changed. This entire process is called diffing.

When React knows which virtual DOM has changed, then React updated those objects. and only those object, in the real DOM. React only updates the necessary parts of the DOM. React's reputation for performance comes largely from this innovation.

In brief, here is what happens when we update the DOM in React:

  1. The entire virtual DOM gets updated.
  2. The virtual DOM gets compared to what it looked like before you updated it. React matches out which objects have changed.
  3. The changed objects and the changed objects only get updated on the real DOM.
  4. Changes on the real DOM cause the screen to change finally.
↥ back to top

Q. What is the difference between DOM and virtual DOM?

1. DOM:

DOM stands for “Document Object Model”. The HTML DOM provides an interface (API) to traverse and modify the nodes. It contains methods like getElementById() or removeChild().

The DOM is represented as a tree data structure. Because of that, the changes and updates to the DOM are fast. But after the change, the updated element and it's children have to be re-rendered to update the application UI. The re-rendering or re-painting of the UI is what makes it slow.

2. Virtual DOM:

The virtual DOM is only a virtual representation of the DOM. Every time the state of our application changes, the virtual DOM gets updated instead of the real DOM.

The Virtual DOM is an abstraction of the HTML DOM. It is lightweight and detached from the browser-specific implementation details. Since the DOM itself was already an abstraction, the virtual DOM is, in fact, an abstraction of an abstraction.

Why Virtual DOM is faster:

When new elements are added to the UI, a virtual DOM, which is represented as a tree is created. Each element is a node on this tree. If the state of any of these elements changes, a new virtual DOM tree is created. This tree is then compared or “diffed” with the previous virtual DOM tree.

Once this is done, the virtual DOM calculates the best possible method to make these changes to the real DOM. This ensures that there are minimal operations on the real DOM. Hence, reducing the performance cost of updating the real DOM.

Pros of Virtual DOM:

Real DOM and Virtual DOM

↥ back to top

Q. Explain DOM diffing?

Once the Virtual DOM is created, React compares this new representation with a snapshot of the previous version of the virtual DOM to see exactly which elements have changed.

Once the difference is known, React updates only those objects that differ on the actual DOM and the browser re-paints the screen. The next time state or props changes for a component in the application, a new virtual DOM tree of React elements will be created and the process will repeat.

The process of checking the difference between the new Virtual DOM tree and the old Virtual DOM tree is called diffing. Diffing is accomplished by a heuristic O(n) algorithm. During this process, React will deduce the minimum number of steps needed to update the real DOM, eliminating unnecessary costly changes. This process is also referred to as reconciliation.

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.”
↥ back to top

Q. How Diff Algorithm is implemented in React.js?

The main work of a diff algorithm is to find a heuristic to change anything from a state to another. When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.

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. When tearing down a tree, old DOM nodes are destroyed. Component instances receive componentWillUnmount().

When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive UNSAFE_componentWillMount() and then componentDidMount(). Any state associated with the old tree is lost.

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.

Example: By comparing these two elements, React knows to only modify the className on the underlying DOM node.

<div className="before" title="React JS" />

<div className="after" title="React JS" />

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 UNSAFE_componentWillReceiveProps(), UNSAFE_componentWillUpdate() and componentDidUpdate() on the underlying instance.

Recursing On Children:

By default, 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>

React will match the two <li>first</li> trees, match the two <li>second</li> trees, and then insert the <li>third</li> tree.

Keys:

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 to our inefficient example above 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>
↥ back to top

Q. What is reconciliation in React?

Reconciliation is the process React uses to determine how to efficiently update the real browser DOM when a component's state or props change. Instead of rebuilding the entire UI from scratch, React compares a new representation of the interface with the previous one and applies only the necessary changes.

How the Process Works

Key Rules of the Diffing Algorithm

To keep the reconciliation process fast (complexity), React follows two primary heuristic assumptions:

Evolution: React Fiber

Since React 16, the core reconciliation engine has been reimplemented as React Fiber. This modern architecture allows React to break rendering work into small units and pause, resume, or prioritize them, making complex UIs much more responsive by not blocking the main thread

↥ back to top

Q. What are portals in React?

Portals provide a quick and seamless way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

Normally, a functional or a class component renders a tree of React elements (usually generated from JSX). The React element defines how the DOM of the parent component should look.

Syntax:

import { createPortal } from 'react-dom';

function MyPortal({ children }) {
  // Renders 'children' into the document body, 
  // away from this component physical DOM parent.
  return createPortal(children, document.body);
}

Features:

Installation:

npm install react-portal --save

Example:

/**
 * React Portal
 */
import PortalExample from "./PortalExample.js";

export default function App() {
  return (
    <div>
      <h2>React Component Example</h2>
      <PortalExample />
    </div>
  );
}


/**
 * Portal Component
 */
import { createPortal } from 'react-dom';

export default function PortalExample() {
  return createPortal(
    <h2>React Portal Example</h2>,
    document.getElementById("portal-root")
  );
}

Now, open the Index.html file and add a <div id="portal-root"></div> element to access the child component outside the root node.

<!-- index.html -->

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <meta charset="utf-8" />  
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />  
    <meta name="viewport" content="width=device-width, initial-scale=1" />  
    <meta name="theme-color" content="#000000" />  
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />  
    <title>React App using Portal</title>  
  </head>  
  <body>  
    <noscript>It is required to enable JavaScript to run this app.</noscript>  
    <div id="root"></div>  
    <div id="portal-root"></div>  
  </body>  
</html>  

Try this example on CodeSandbox

↥ back to top

Q. What is ReactDOMServer?

ReactDOMServer is an object that enables you to render React components to static HTML markup, typically used on a Node.js server for Server-Side Rendering (SSR).

// ES modules
import ReactDOMServer from 'react-dom/server'
// CommonJS
var ReactDOMServer = require('react-dom/server')

The Server-side rendering (SSR) is a popular technique for rendering a client-side single page application (SPA) on the server and then sending a fully rendered page to the client. This allows for dynamic components to be served as static HTML markup.

Example:

Creating an Express Server:

npm install express

All the content inside the build folder is going to be served as-is, statically by Express.

/**
 * server/server.js
 */
import path from 'path'
import fs from 'fs'

import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server'

import App from '../src/App'

const PORT = 8080
const app = express()

const router = express.Router()

const serverRenderer = (req, res, next) => {
  fs.readFile(path.resolve('./build/index.html'), 'utf8', (err, data) => {
    if (err) {
      console.error(err)
      return res.status(500).send('An error occurred')
    }
    return res.send(
      data.replace(
        '<div id="root"></div>',
        `<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
      )
    )
  })
}
router.use('^/$', serverRenderer)

router.use(
  express.static(path.resolve(__dirname, '..', 'build'), { maxAge: '30d' })
)

// tell the app to use the above rules
app.use(router)

// app.use(express.static('./build'))
app.listen(PORT, () => {
  console.log(`SSR running on port ${PORT}`)
})

Now, in the client application, in your src/index.js, instead of calling ReactDOM.render():

ReactDOM.render(<App />, document.getElementById('root'))

call ReactDOM.hydrate(), which is the same but has the additional ability to attach event listeners to existing markup once React loads:

ReactDOM.hydrate(<App />, document.getElementById('root'))

All the Node.js code needs to be transpiled by Babel, as server-side Node.js code does not know anything about JSX, nor ES Modules (which we use for the include statements).

Babel Package:

npm install @babel/register @babel/preset-env @babel/preset-react ignore-styles

Let's create an entry point in server/index.js:

require('ignore-styles')

require('@babel/register')({
  ignore: [/(node_modules)/],
  presets: ['@babel/preset-env', '@babel/preset-react']
})

require('./server')

Build the React application, so that the build/ folder is populated and run this:

# Build App
npm run build

# Run App on Express
node server/index.js
↥ back to top

Q. How can automated tooling be used to improve the accessibility of a React application?

There are two main categories of automated tools that can be used to identify accessibility issues:

1. Static Analysis Tools (Compile-time)

Linting tools like ESLint with the eslint-plugin-jsx-a11y plugin analyze React projects at the component level — catching issues before code even runs.

Examples of issues it catches:

2. Browser Tools (Runtime)

Browser accessibility tools such as aXe and Google Lighthouse perform automated accessibility at the app level. This can discover more real-world issues, because a browser is used to simulate the way that a user interacts with a website.

↥ back to top

Q. How to do SEO on react?

React applications are typically Single Page Applications (SPAs) that render content on the client-side, which can pose challenges for SEO since search engine crawlers may not execute JavaScript. Here are the main approaches to optimize React apps for SEO:

1. Server-Side Rendering (SSR):

SSR renders React components on the server and sends fully rendered HTML to the client. This ensures search engines can crawl and index your content.

Use Next.js to render pages on the server before sending HTML to the client:

npm install next react react-dom
// pages/index.js
export default function Home({ data }) {
  return (
    <div>
      <h1>Welcome to SEO-Optimized React</h1>
      <p>{data.content}</p>
    </div>
  )
}

// This function runs on the server
export async function getServerSideProps() {
  const data = await fetchDataFromAPI()
  return {
    props: { data }
  }
}

2. Static Site Generation (SSG):

Pre-render pages at build time with getStaticProps() / getStaticPaths() — best for content that doesn't change frequently (blogs, docs).

// pages/blog/[slug].js
export default function BlogPost({ post }) {
  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  )
}

export async function getStaticProps({ params }) {
  const post = await getPostBySlug(params.slug)
  return {
    props: { post }
  }
}

export async function getStaticPaths() {
  const posts = await getAllPosts()
  return {
    paths: posts.map(post => ({
      params: { slug: post.slug }
    })),
    fallback: false
  }
}

3. Dynamic Meta Tags (React Helmet)

Use react-helmet-async to set page-specific <title>, <meta> descriptions, and Open Graph tags per route.

npm install react-helmet-async
import { Helmet } from 'react-helmet-async'

function ProductPage({ product }) {
  return (
    <>
      <Helmet>
        <title>{product.name} | My Store</title>
        <meta name="description" content={product.description} />
        <meta property="og:title" content={product.name} />
        <meta property="og:description" content={product.description} />
        <meta property="og:image" content={product.image} />
        <meta property="og:url" content={`https://mystore.com/products/${product.id}`} />
        <meta name="twitter:card" content="summary_large_image" />
        <link rel="canonical" href={`https://mystore.com/products/${product.id}`} />
      </Helmet>
      <div>
        <h1>{product.name}</h1>
        <p>{product.description}</p>
      </div>
    </>
  )
}

4. Pre-rendering

Use react-snap to generate static HTML snapshots at build time — a lighter alternative to full SSR.

npm install react-snap --save-dev
// package.json
{
  "scripts": {
    "postbuild": "react-snap"
  },
  "reactSnap": {
    "inlineCss": true,
    "minifyHtml": true
  }
}

5. Dynamic Rendering:

Serve pre-rendered content to search engines while serving the SPA to users.

// server.js (Express example)
const express = require('express')
const puppeteer = require('puppeteer')
const app = express()

app.get('*', async (req, res) => {
  const isBot = /bot|googlebot|crawler|spider|robot|crawling/i.test(
    req.headers['user-agent']
  )
  
  if (isBot) {
    // Serve pre-rendered content to bots
    const browser = await puppeteer.launch()
    const page = await browser.newPage()
    await page.goto(`http://localhost:3000${req.url}`)
    const html = await page.content()
    await browser.close()
    res.send(html)
  } else {
    // Serve SPA to regular users
    res.sendFile('index.html')
  }
})
↥ back to top

Q. Explain SEO Best Practices for React?

1. Semantic HTML:

Use proper HTML5 elements (<article>, <header>, <section>, etc.) instead of generic <div> tags. This helps crawlers understand your content structure.

function Article({ title, content }) {
  return (
    <article>
      <header>
        <h1>{title}</h1>
      </header>
      <section>{content}</section>
    </article>
  )
}

2. Structured Data (JSON-LD):

Embed schema.org markup to help search engines understand entities like products, articles, and organizations.

function ProductStructuredData({ product }) {
  const structuredData = {
    "@context": "https://schema.org/",
    "@type": "Product",
    "name": product.name,
    "image": product.image,
    "description": product.description,
    "brand": {
      "@type": "Brand",
      "name": product.brand
    },
    "offers": {
      "@type": "Offer",
      "price": product.price,
      "priceCurrency": "USD"
    }
  }

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML=
    />
  )
}

3. Image Optimization:

Always include:

function OptimizedImage({ src, alt }) {
  return (
    <img
      src={src}
      alt={alt}
      loading="lazy"
      width="800"
      height="600"
    />
  )
}

4. URL Structure:

Use clean, descriptive paths instead of hash-based routing:

// Good SEO-friendly URLs
<Link to="/blog/react-seo-guide">React SEO Guide</Link>

// Avoid hash-based routing
// Bad: /#/blog/react-seo-guide

5. sitemap.xml and robots.txt:

Place these in /public:

<!-- public/sitemap.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <lastmod>2026-02-03</lastmod>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/about</loc>
    <lastmod>2026-02-03</lastmod>
    <priority>0.8</priority>
  </url>
</urlset>
# public/robots.txt
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml
↥ back to top

Popular React SEO Tools:

Reference:

↥ back to top