BC.

Full Stack Web & Mobile App Developer

React.js Interview Questions

Found 399 questions

31. Why are state updates asynchronous?

State updates are asynchronous because React batches multiple updates together and processes them efficiently. This improves performance by reducing unnecessary re-renders and ensuring the UI updates in an optimized way.

Example

function Counter() {
  const [count, setCount] = React.useState(0);

  const handleClick = () => {
    setCount(count + 1);

    console.log(count); // Still shows old value
  };
}

The console.log shows the old value because React schedules the state update and applies it during the next render.

Benefits

  • Better performance through batching

  • Fewer re-renders

  • Smoother UI updates

  • More efficient rendering process

Getting the Latest Value

setCount(prev => prev + 1);

Use the functional update form when the new state depends on the previous state.

Summary: State updates are asynchronous so React can batch and optimize updates, reducing unnecessary renders and improving application performance.

32. What is batching in React?

Batching is React's process of grouping multiple state updates into a single re-render. Instead of re-rendering after every state update, React combines them and updates the UI once, improving performance.

Example

function App() {
  const [count, setCount] = React.useState(0);
  const [name, setName] = React.useState("");

  const handleClick = () => {
    setCount(c => c + 1);
    setName("Bhuvanesh");
  };

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

When the button is clicked, React batches both state updates and performs only one re-render.

Benefits

  • Fewer re-renders

  • Better performance

  • More efficient UI updates

React 18

React 18 introduced automatic batching, which batches updates in more situations, including:

  • Event handlers

  • setTimeout

  • Promises

  • Async functions

Example

setTimeout(() => {
  setCount(c => c + 1);
  setName("Bhuvanesh");
}, 1000);

In React 18, these updates are batched into a single re-render.

Summary: Batching combines multiple state updates into one render cycle, making React applications faster and more efficient.

33. What is useEffect?

useEffect is a React Hook used to perform side effects in functional components. Side effects include fetching data, setting up subscriptions, timers, or updating the DOM after a component renders.

Example

function App() {
  React.useEffect(() => {
    console.log("Component rendered");
  });

  return <h1>Hello</h1>;
}

With Dependency Array

Run only when count changes:

function App() {
  const [count, setCount] = React.useState(0);

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

Common Uses

  • API calls

  • Timers (setInterval, setTimeout)

  • Event listeners

  • DOM updates

  • Subscriptions

Cleanup Function

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

  return () => clearInterval(timer);
}, []);

Summary: useEffect lets you run side effects after a component renders and optionally clean them up when the component updates or unmounts.

34. How does the dependency array in useEffect work?

The dependency array tells React when to run the effect. React compares the dependency values after each render and runs the effect only if one of them has changed.

1. No Dependency Array

Runs after every render.

React.useEffect(() => {
  console.log("Runs on every render");
});

2. Empty Dependency Array ([])

Runs only once after the initial render.

React.useEffect(() => {
  console.log("Runs once");
}, []);

3. With Dependencies

Runs on the initial render and whenever a dependency changes.

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

Multiple Dependencies

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

Example

function Counter() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]);

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

Dependency Array

When Effect Runs

No array

After every render

[]

Once after initial render

[value]

Initial render + when value changes

[a, b]

Initial render + when a or b changes

Summary: The dependency array controls when useEffect runs by watching specific values and re-running the effect only when those values change.

35. What are common mistakes with useEffect dependencies?

The most common mistakes happen when dependencies are missing, incorrect, or cause unnecessary re-renders.

1. Missing Dependencies

React.useEffect(() => {
  console.log(count);
}, []); // count is missing

The effect uses count but doesn't track it, which can lead to stale values.

✅ Correct

React.useEffect(() => {
  console.log(count);
}, [count]);

2. Infinite Re-render Loops

React.useEffect(() => {
  setCount(count + 1);
}, [count]);

The effect updates count, which triggers the effect again, creating an infinite loop.

3. Using Objects or Arrays as Dependencies

const user = { name: "John" };

React.useEffect(() => {
  console.log(user);
}, [user]);

A new object is created on every render, so the effect runs every time.

4. Using Functions as Dependencies

const handleClick = () => {};

React.useEffect(() => {
  console.log("Effect");
}, [handleClick]);

The function is recreated on every render, causing the effect to run repeatedly.

5. Ignoring ESLint Warnings

React's Hooks ESLint plugin warns about missing dependencies. Ignoring these warnings can lead to bugs and stale data.

Mistake

Problem

Missing dependencies

Stale values or bugs

Updating tracked state inside effect

Infinite loops

Object/array dependencies

Unnecessary effect runs

Function dependencies

Repeated effect execution

Ignoring ESLint warnings

Hard-to-find bugs

Summary: Always include all values used inside the effect as dependencies, and be careful with state updates, objects, arrays, and functions to avoid bugs and unnecessary re-renders.

36. How does cleanup work in useEffect?

A cleanup function is used to remove or stop side effects created by useEffect.

React runs the cleanup function:

  • Before the effect runs again (when dependencies change)

  • When the component unmounts

Example

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

  return () => {
    clearInterval(timer);
  };
}, []);

How It Works

  1. Effect runs and starts the timer.

  2. Component unmounts (or dependencies change).

  3. Cleanup function runs and clears the timer.

Common Uses

  • Removing event listeners

  • Clearing timers (setTimeout, setInterval)

  • Canceling subscriptions

  • Closing WebSocket connections

  • Aborting API requests

Event Listener Example

React.useEffect(() => {
  const handleResize = () => {
    console.log(window.innerWidth);
  };

  window.addEventListener("resize", handleResize);

  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, []);

Why Cleanup Is Important

Without cleanup, resources may continue running after the component is gone, causing memory leaks and unexpected behavior.

Summary: Cleanup functions are returned from useEffect and are used to remove side effects before re-running the effect or when the component unmounts.

37. What memory leaks can occur in React components?

Memory leaks happen when resources created by a component are not cleaned up after the component is removed. This can cause unnecessary memory usage, performance issues, and unexpected behavior.

Common Causes

1. Uncleaned Timers

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

  return () => clearInterval(timer);
}, []);

Without clearInterval, the timer keeps running even after the component unmounts.


2. Event Listeners Not Removed

React.useEffect(() => {
  const handleResize = () => {};

  window.addEventListener("resize", handleResize);

  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, []);

3. Unclosed Subscriptions

Examples:

  • WebSocket connections

  • Chat subscriptions

  • External library listeners

return () => socket.close();

4. Pending API Requests

A request may finish after the component has unmounted.

React.useEffect(() => {
  const controller = new AbortController();

  fetch("/api/data", {
    signal: controller.signal
  });

  return () => controller.abort();
}, []);

Signs of Memory Leaks

  • Increasing memory usage

  • Slow application performance

  • Duplicate event handlers

  • Unexpected background activity

Summary

Memory leaks usually occur when timers, event listeners, subscriptions, or async operations are not cleaned up. Using the useEffect cleanup function helps prevent these issues.

38. What is useRef used for?

useRef is a React Hook used to store a mutable value that persists across renders without causing a re-render when it changes. It is commonly used to access DOM elements and keep values between renders.

Accessing a DOM Element

function InputFocus() {
  const inputRef = React.useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focusInput}>
        Focus
      </button>
    </>
  );
}

Storing a Value

function Counter() {
  const renderCount = React.useRef(0);

  renderCount.current++;

  return <p>Renders: {renderCount.current}</p>;
}

Common Uses

  • Access DOM elements

  • Focus inputs

  • Store timer IDs

  • Keep previous values

  • Store mutable data without re-rendering

Difference from State

Feature

useRef

useState

Causes re-render when updated

No

Yes

Stores mutable values

Yes

Yes

Common use

DOM access, persistent values

UI state

Summary: useRef stores values that persist between renders and is often used for DOM access or keeping mutable data without triggering re-renders.

39. How does useRef differ from state?

Feature

useRef

useState

Causes Re-render When Updated

No

Yes

Purpose

Store mutable values or DOM references

Store UI state

Update Method

ref.current = value

setState(value)

UI Updates Automatically

No

Yes

Persists Across Renders

Yes

Yes

useRef Example

function App() {
  const countRef = React.useRef(0);

  const increment = () => {
    countRef.current++;
    console.log(countRef.current);
  };

  return <button onClick={increment}>Increment</button>;
}

Updating countRef.current does not re-render the component.

useState Example

function App() {
  const [count, setCount] = React.useState(0);

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

Updating state causes React to re-render and update the UI.

When to Use

  • useState → Data that affects what the user sees.

  • useRef → DOM elements, timer IDs, previous values, or mutable data that should not trigger re-renders.

Summary: useState is for UI data that should trigger re-renders when it changes. useRef is for storing persistent values or DOM references without causing re-renders.

40. What is useMemo?

No Content.