Top 100 React Interview Questions and Answers (2026 Updated)

Prepare for your React job interview with the top 100 most asked React interview questions and answers. Covers hooks, lifecycle, Redux, performance, and real-world coding questions.

What is React?

React is an open-source JavaScript library developed by Facebook for building user interfaces using a component-based architecture.

What are the main features of React?

  • Component-Based Architecture: React builds UI using reusable components.
  • Virtual DOM: Updates only the changed parts of the UI for better performance.
  • JSX: Allows writing HTML inside JavaScript for readable code.
  • One-Way Data Binding: Data flows from parent to child, making state predictable.
  • Declarative UI: Describe what the UI should look like, React updates it automatically.
  • Reusability: Components can be reused across the application.
  • Hooks: Use state and lifecycle features in functional components.
  • Strong Ecosystem: Large community with tools like React Router and Redux.

What is JSX?

JSX (JavaScript XML) is a syntax extension for JavaScript used in React that allows developers to write HTML-like code inside JavaScript.

It makes UI code more readable and easier to understand by combining structure and logic in one place.

Behind the scenes, JSX is converted into normal JavaScript using React.createElement().

Example:

const element = <h1>Hello World</h1>;
    

Why is JSX better than normal JS?

JSX is better than normal JavaScript for building UI because it makes the code more readable, maintainable, and closer to how the actual UI looks.

  • More Readable: UI structure looks like real HTML.
  • Less Code: No need to write long createElement functions.
  • Easier Debugging: Errors point directly to UI lines.
  • Better Maintainability: Structure and logic stay together.
  • Faster Development: Developers can build interfaces quickly.

Without JSX:

React.createElement("h1", null, "Hello World");
    

With JSX:

<h1>Hello World</h1>
    

What is Virtual DOM?

The Virtual DOM is a lightweight in-memory copy of the real DOM that React uses to improve performance when updating the UI.

Instead of updating the real DOM directly, React first updates the Virtual DOM, compares it with the previous version (called diffing), and then updates only the changed parts in the real DOM.

  • Faster updates: Only necessary elements are re-rendered.
  • Better performance: Reduces costly DOM operations.
  • Efficient rendering: Makes large applications smoother.

In simple words: React updates the UI smartly, not fully.

How does Virtual DOM work?

The Virtual DOM works by creating a virtual representation of the real DOM and updating only the parts that have changed.

  • Step 1: React creates a Virtual DOM when the app loads.
  • Step 2: When state or props change, a new Virtual DOM is created.
  • Step 3: React compares the new Virtual DOM with the old one (diffing).
  • Step 4: Only the differences are applied to the real DOM (reconciliation).

This process makes React faster and more efficient than directly updating the real DOM.

What is reconciliation in React?

Reconciliation is the process by which React updates the real DOM efficiently by comparing the old Virtual DOM with the new Virtual DOM.

When a component’s state or props change, React creates a new Virtual DOM tree and finds the minimum number of changes needed to update the real DOM.

  • Diffing: React compares old and new Virtual DOM.
  • Minimal Updates: Only changed elements are updated.
  • Better Performance: Avoids unnecessary re-rendering.

In simple terms: Reconciliation is React’s smart way of keeping the UI in sync with data.

What is a component?

A component is an independent and reusable piece of UI in React that represents a part of the user interface.

Each component contains its own logic, structure, and styling, and can be combined with other components to build a complete application.

  • Reusable: Can be used multiple times.
  • Independent: Manages its own data and behavior.
  • Composable: Can be nested inside other components.

Example:

function Button() {
  return <button>Click Me</button>;
}
    

Difference between Functional and Class Components

Functional and Class components are two ways to create components in React, but functional components are now the preferred modern approach.

Functional Components Class Components
Written as simple JavaScript functions. Written using ES6 classes.
Uses Hooks for state and lifecycle. Uses lifecycle methods like componentDidMount.
Less code and easier to read. More boilerplate code.
Better performance and recommended. Older approach, not recommended for new projects.
No need to use this. Uses this keyword.

In modern React development, functional components with hooks are preferred over class components.

What are props?

Props (short for properties) are used to pass data from one component to another in React.

Props allow components to be dynamic and reusable by receiving different values from their parent components.

  • Read-only: Props cannot be modified inside the child component.
  • One-way: Data flows from parent to child.
  • Reusable: Same component can behave differently with different props.

Example:

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

// Usage
<Greeting name="Manish" />
    

What is state?

State is an object that stores dynamic data in a React component and controls how the component behaves and renders.

When state changes, React automatically re-renders the component to reflect the new data in the UI.

  • Mutable: State can change over time.
  • Local: State belongs to a specific component.
  • Triggers re-render: UI updates when state changes.

Example:

const [count, setCount] = useState(0);

<button onClick={() => setCount(count + 1)}>
  Clicked {count} times
</button>
    

Difference between Props and State

Props and State are both used to manage data in React, but they serve different purposes.

Props State
Passed from parent to child. Managed within the component.
Read-only (cannot be modified). Can be modified using setState/useState.
Used for configuration. Used for dynamic data.
Does not trigger change itself. Triggers re-render when updated.
External data. Internal data.

In short: Props are for passing data, State is for managing data.

Why is state immutable?

State is immutable in React because it ensures predictable behavior, better performance, and reliable UI updates.

  • Predictable Updates: React can easily track changes when new state objects are created.
  • Efficient Re-rendering: React compares old and new state using references.
  • Prevents Bugs: Direct mutation can cause unexpected side effects.
  • Time Travel Debugging: Previous states can be stored and inspected.

Instead of modifying state directly, React creates a new copy of state:

❌ state.count = state.count + 1

✅ setState({ count: state.count + 1 })
    

In simple terms: Immutability makes React fast, stable, and easier to debug.

What is setState?

setState is a method used in React class components to update the state and trigger a re-render of the component.

When setState() is called, React merges the new state with the existing state and updates the UI accordingly.

  • Asynchronous: State updates may not happen immediately.
  • Triggers re-render: Updates the UI automatically.
  • Merges state: Only updates specified fields.

Example:

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

In modern React with functional components, the same behavior is achieved using:

const [count, setCount] = useState(0);
setCount(count + 1);
    

Why should we not modify state directly?

We should not modify state directly because React may not detect the change, which can lead to unexpected behavior and UI not updating properly.

  • No Re-render: Direct mutation does not trigger re-render.
  • Breaks Immutability: React relies on immutable state.
  • Causes Bugs: Leads to unpredictable application behavior.
  • Hard to Debug: React cannot track changes correctly.

Wrong way:

this.state.count = this.state.count + 1; // ❌
    

Correct way:

this.setState({ count: this.state.count + 1 }); // ✅
    

In simple words: Always use setState or state setter functions to update state.

What are hooks?

Hooks are special functions in React that allow you to use state and other React features inside functional components.

Before hooks, these features were only available in class components. Hooks make functional components more powerful and easier to write.

  • Enable state: Use state in functional components.
  • Use lifecycle features: Handle side effects.
  • Reuse logic: Share logic between components.
  • Cleaner code: No need for classes or this keyword.

Common hooks:

  • useState
  • useEffect
  • useContext
  • useRef
  • useMemo

Example:

const [count, setCount] = useState(0);
    

Why were hooks introduced?

Hooks were introduced to solve problems with class components and make state management and lifecycle logic easier in functional components.

  • Remove class complexity: No need to use classes and this keyword.
  • Reuse logic easily: Share logic between components.
  • Cleaner code: Less boilerplate.
  • Better readability: Easier to understand and maintain.
  • Avoid lifecycle confusion: No multiple lifecycle methods.

Before hooks, developers had to use patterns like HOCs and Render Props, which made code complex and hard to reuse.

In simple terms: Hooks made React simpler, cleaner, and more powerful.

What is useState?

useState is a React hook that allows you to add state to functional components.

It returns an array with two values: the current state and a function to update it.

  • Manages local state in functional components.
  • Triggers re-render when state changes.
  • Replaces setState in functional components.

Syntax:

const [value, setValue] = useState(initialValue);
    

Example:

const [count, setCount] = useState(0);
setCount(count + 1);
    

What is useEffect?

useEffect is a React hook used to handle side effects in functional components.

Side effects include tasks like data fetching, subscriptions, timers, and manually updating the DOM.

  • Runs after render by default.
  • Replaces lifecycle methods like componentDidMount and componentDidUpdate.
  • Used for external operations (API calls, events).

Syntax:

useEffect(() => {
  // side effect
}, [dependencies]);
    

Example:

useEffect(() => {
  fetchData();
}, []);
    

In simple words: useEffect runs code when something changes.

Difference between useEffect and Lifecycle Methods

Both useEffect and lifecycle methods are used to handle side effects in React, but they work in different ways.

useEffect Lifecycle Methods
Used in functional components. Used in class components.
Single hook replaces multiple methods. Uses separate methods.
Depends on dependency array. Uses different lifecycle phases.
Cleaner and less boilerplate. More complex and verbose.
Modern and recommended. Older approach.

In short: useEffect simplifies lifecycle logic into one powerful hook.

What is dependency array in useEffect?

The dependency array in useEffect is a list of values that tells React when to run the effect.

React compares the current and previous values in the dependency array. If any value changes, the effect runs again.

  • Empty array ([]): Runs only once (on mount).
  • No array: Runs on every render.
  • With values: Runs when those values change.

Example:

useEffect(() => {
  console.log("Count changed");
}, [count]);
    

In simple words: Dependency array controls when useEffect runs.

What happens if dependency array is empty?

If the dependency array in useEffect is empty ([]), the effect runs only once after the initial render.

This behavior is similar to componentDidMount in class components.

  • Runs only once: Executes after the component is mounted.
  • No re-run: Does not run again on state or prop changes.
  • Best for: API calls, subscriptions, initial setup.

Example:

useEffect(() => {
  fetchData();
}, []);
    

In simple words: Empty dependency array means “run this effect only once”.

What is useRef?

useRef is a React hook used to create a mutable reference that persists across renders without causing a re-render.

It is mainly used to directly access DOM elements or to store values that should not trigger UI updates.

  • Access DOM: Like focusing input fields.
  • No re-render: Changing ref does not update UI.
  • Persist value: Keeps value between renders.

Example:

const inputRef = useRef(null);

<input ref={inputRef} />
inputRef.current.focus();
    

In simple words: useRef is used when you need to remember something without causing a re-render.

Difference between useRef and useState

Both useRef and useState are used to store values in React, but they behave very differently.

useRef useState
Does NOT trigger re-render. Triggers re-render on update.
Used for DOM access or mutable values. Used for UI-related data.
Value stored in .current. Value stored directly in variable.
Changes are invisible to UI. Changes update the UI.
Good for timers, previous values. Good for form data, counters.

In short: useState is for data that affects UI, useRef is for data that should persist without re-rendering.

What is useMemo?

useMemo is a React hook used to memoize (cache) the result of an expensive calculation so that it is not recalculated on every render.

It helps improve performance by recomputing the value only when its dependencies change.

  • Optimizes performance: Avoids unnecessary calculations.
  • Caches result: Stores computed value.
  • Recomputes only when needed: Based on dependency array.

Syntax:

const value = useMemo(() => {
  return expensiveCalculation();
}, [dependencies]);
    

Example:

const squared = useMemo(() => {
  return num * num;
}, [num]);
    

In simple words: useMemo remembers a value so React doesn’t recompute it again and again.

What is useCallback?

useCallback is a React hook used to memoize (cache) a function so that the same function reference is not recreated on every render.

It is mainly used to optimize performance when passing functions as props to child components.

  • Caches functions: Prevents unnecessary re-creation.
  • Improves performance: Avoids unwanted re-renders.
  • Works with dependency array: Recreates function only when needed.

Syntax:

const memoizedFn = useCallback(() => {
  doSomething();
}, [dependencies]);
    

Example:

const handleClick = useCallback(() => {
  console.log("Clicked");
}, []);
    

In simple words: useCallback remembers a function so React does not create it again on every render.

What is useContext?

useContext is a React hook used to access values from React Context without passing props manually through every level.

It helps in sharing global data like theme, user information, or language settings across components.

  • Avoids prop drilling: No need to pass props deeply.
  • Access global state: Use shared data easily.
  • Cleaner code: Reduces complexity.

Example:

const ThemeContext = React.createContext();

const theme = useContext(ThemeContext);
    

In simple words: useContext lets components read shared data directly.

What is a custom hook?

A custom hook is a JavaScript function in React that starts with the word use and is used to reuse logic across multiple components.

It allows you to extract component logic into a reusable function without repeating code.

  • Reusable logic: Share logic between components.
  • Cleaner code: Reduces duplication.
  • Uses hooks: Can use built-in hooks inside.

Example:

function useCounter() {
  const [count, setCount] = useState(0);
  return { count, setCount };
}
    

In simple words: Custom hooks let you create your own reusable hooks.

Rules of Hooks

The Rules of Hooks are guidelines that must be followed to use React hooks correctly.

  • Only call hooks at the top level: Do not call hooks inside loops, conditions, or nested functions.
  • Only call hooks from React functions: Use hooks only inside functional components or custom hooks.

These rules ensure that hooks are called in the same order on every render.

Wrong example:

if (isLoggedIn) {
  useState(0); // ❌
}
    

Correct example:

const [count, setCount] = useState(0); // ✅
    

What are lifecycle methods?

Lifecycle methods are special methods in React class components that are called at different stages of a component’s life.

They allow developers to run code when a component is created, updated, or removed from the DOM.

  • Mounting: When component is created.
  • Updating: When state or props change.
  • Unmounting: When component is removed.

Common lifecycle methods:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

In modern React, lifecycle logic is mostly handled using hooks like useEffect.

Phases of lifecycle in React

The React component lifecycle is divided into three main phases that describe how a component is created, updated, and removed.

  • Mounting: When the component is created and inserted into the DOM. Example methods: constructor, render, componentDidMount
  • Updating: When the component re-renders due to changes in state or props. Example methods: render, componentDidUpdate
  • Unmounting: When the component is removed from the DOM. Example method: componentWillUnmount

In modern React, these phases are handled using hooks like useEffect.

componentDidMount vs useEffect

Both componentDidMount and useEffect are used to run code after a component is rendered, but they are used in different types of components.

componentDidMount useEffect
Used in class components. Used in functional components.
Runs only once after mount. Runs based on dependency array.
Cannot handle updates easily. Handles mount, update, unmount.
Older approach. Modern and recommended.

In short: componentDidMount is for class components, useEffect is for functional components and is more powerful.

componentDidUpdate equivalent in hooks?

The equivalent of componentDidUpdate in hooks is useEffect with a dependency array.

When you pass dependencies to useEffect, the effect runs every time those values change, which is similar to componentDidUpdate.

Example:

useEffect(() => {
  console.log("Count updated");
}, [count]);
    

This runs after every update of count.

  • componentDidUpdate: Runs after update in class.
  • useEffect with deps: Runs after change in hooks.

In short: useEffect with dependencies replaces componentDidUpdate.

componentWillUnmount equivalent?

The equivalent of componentWillUnmount in hooks is the cleanup function inside useEffect.

The cleanup function runs when the component is about to be removed from the DOM.

Example:

useEffect(() => {
  const timer = setInterval(() => {
    console.log("Running...");
  }, 1000);

  return () => {
    clearInterval(timer); // cleanup
  };
}, []);
    
  • componentWillUnmount: Runs before component is destroyed.
  • Cleanup in useEffect: Runs before component is removed.

In simple words: The return function inside useEffect replaces componentWillUnmount.

When does a component re-render?

A React component re-renders whenever there is a change in its state, props, or context.

  • State changes: When setState or state setter is called.
  • Props change: When parent passes new props.
  • Context changes: When context value updates.
  • Force update: Using forceUpdate().

A component also re-renders if its parent re-renders (unless optimized with memo or shouldComponentUpdate).

In simple words: Any data change that affects the component causes re-render.

What causes re-render in React?

A re-render in React happens when React detects that some data used by the component has changed.

  • State changes: When state is updated using setState or useState.
  • Props changes: When a parent passes new props.
  • Context changes: When context value updates.
  • Parent re-render: Child re-renders if parent re-renders.
  • forceUpdate(): Manually forces a re-render (not recommended).

Note: A re-render does not always mean real DOM update. React first compares using Virtual DOM.

In simple words: Any data change related to UI triggers re-render.

How to prevent unnecessary re-renders?

Unnecessary re-renders happen when a component updates even though its data has not meaningfully changed. React provides several ways to optimize this.

  • React.memo: Prevents re-render if props are the same.
  • useMemo: Memoizes expensive calculated values.
  • useCallback: Memoizes function references.
  • Proper state design: Keep state minimal and local.
  • Avoid anonymous functions: Inside JSX when not needed.
  • Key optimization: Use stable keys in lists.

Example using React.memo:

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

In simple words: Cache values and functions, and avoid updating components when data hasn’t changed.

What is React.memo?

React.memo is a higher-order component used to prevent unnecessary re-renders of functional components.

It memoizes the component and re-renders it only when its props change.

  • Optimizes performance: Skips re-render if props are same.
  • Shallow comparison: Compares previous and new props.
  • Works with functional components only.

Example:

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

In simple words: React.memo remembers the component and skips re-render if nothing changed.

What is memoization?

Memoization is an optimization technique used to store the result of expensive function calls and reuse them when the same inputs occur again.

Instead of recalculating a value every time, the previously computed result is returned from memory (cache).

  • Improves performance: Avoids repeated calculations.
  • Reduces processing: Saves CPU work.
  • Used in React: Through useMemo, useCallback, React.memo.

Example:

function square(n) {
  return n * n;
}

const memo = {};
function memoSquare(n) {
  if (memo[n]) return memo[n];
  return memo[n] = square(n);
}
    

In simple words: Memoization means remembering results to avoid doing the same work again.

What is key in React?

A key in React is a special attribute used to uniquely identify elements in a list.

Keys help React understand which items have changed, been added, or removed.

  • Unique: Each key must be unique among siblings.
  • Improves performance: Helps in efficient re-rendering.
  • Avoids bugs: Prevents incorrect UI updates.

Example:

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

In simple words: Keys help React track list items efficiently.

Why keys are important in lists?

Keys are important in lists because they help React efficiently identify which items have changed, been added, or removed.

Without keys, React may re-render the entire list, leading to poor performance and UI bugs.

  • Efficient updates: React updates only changed items.
  • Stable identity: Keeps element identity between renders.
  • Prevents reordering bugs: Correctly handles item movement.

Bad example:

{items.map((item, index) => (
  <li key={index}>{item}</li>
))}
    

Good example:

{items.map(item => (
  <li key={item.id}>{item}</li>
))}
    

In simple words: Keys allow React to update lists smartly and safely.

What is lazy loading?

Lazy loading is a technique where resources are loaded only when they are actually needed.

Instead of loading everything at once, the application loads components, images, or data on demand.

  • Improves performance: Reduces initial load time.
  • Saves bandwidth: Loads only required data.
  • Better user experience: Faster page rendering.

Example in React:

const Profile = React.lazy(() => import("./Profile"));

<Suspense fallback={<div>Loading...</div>}>
  <Profile />
</Suspense>
    

In simple words: Lazy loading means “load only when needed”.

What is React.lazy?

React.lazy is a function used to load components lazily (on demand) instead of loading them at the start.

It helps reduce the initial bundle size and improves application performance.

  • Loads components only when needed.
  • Used with Suspense.
  • Improves page load speed.

Example:

const Dashboard = React.lazy(() => import("./Dashboard"));

<Suspense fallback={<div>Loading...</div>}>
  <Dashboard />
</Suspense>
    

In simple words: React.lazy loads components only when required.

What is Suspense?

Suspense is a React component used to display a fallback UI while waiting for something to load, such as lazy-loaded components.

It is mainly used with React.lazy for code splitting.

  • Shows loading UI: While component is loading.
  • Improves UX: Avoids blank screens.
  • Works with lazy loading.

Example:

<Suspense fallback={<div>Loading...</div>}>
  <LazyComponent />
</Suspense>
    

In simple words: Suspense shows something while waiting.

How do you handle events in React?

Events in React are handled using camelCase event names and by passing a function as the event handler.

React uses a synthetic event system that works the same across different browsers.

  • Use camelCase: onClick, onChange, onSubmit
  • Pass function: Not a string.
  • Prevent default: Using event.preventDefault()

Example:

function handleClick() {
  alert("Button clicked");
}

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

In simple words: React events use functions, not inline strings.

What is Synthetic Event?

A Synthetic Event is a cross-browser wrapper around the browser’s native event system provided by React.

It ensures that events behave consistently across different browsers.

  • Cross-browser compatibility: Same behavior everywhere.
  • Normalized API: Works like native events.
  • Better performance: Uses event pooling.

Example:

function handleClick(e) {
  console.log(e.target.value);
}
    

In simple words: Synthetic events make event handling reliable across browsers.

Controlled vs Uncontrolled Components

Controlled and uncontrolled components are two ways to handle form data in React.

Controlled Uncontrolled
Form data controlled by React state. Form data controlled by DOM.
Uses value and onChange. Uses refs.
Easier validation. Harder validation.
More control and predictability. Less code but less control.

In short: Controlled components use React state, Uncontrolled components rely on the DOM.

How to handle forms in React?

Forms in React are handled by using state to manage input values and updating the state through event handlers.

The most common approach is using controlled components, where form data is stored in React state.

  • Use useState: To store input values.
  • Use onChange: To update state.
  • Use onSubmit: To handle form submission.
  • Prevent default: Using event.preventDefault().

Example:

function Form() {
  const [name, setName] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(name);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        value={name} 
        onChange={e => setName(e.target.value)} 
      />
      <button type="submit">Submit</button>
    </form>
  );
}
    

In simple words: React forms are handled by syncing inputs with state.

How to validate forms?

Form validation in React ensures that user input is correct before submitting the form.

Validation can be done using React state or built-in HTML validation.

  • Client-side validation: Using state and conditions.
  • HTML validation: Using required, pattern, minLength.
  • Show errors: Display error messages.
  • Disable submit: Until form is valid.

Example:

if (!email.includes("@")) {
  setError("Invalid email");
}
    

In simple words: Validation checks user input before submission.