JS Interview
How to get previous value in useEffect in React

How to get previous value in useEffect in React

React functional components do not expose previous values directly within useEffect. To compare current and prior values, developers should persist values between renders using useRef. This approach enables precise change detection, efficient side-effect control, and predictable component behavior.

In React functional components, it is often necessary to compare the current value of a state variable or prop with its previous value. Such comparisons are useful for detecting changes, controlling side effects, preventing redundant operations, or triggering transitions.

React does not provide previous values automatically. Each render produces a new snapshot of component state and props, and useEffect executes using values from the most recent render. Therefore, previous values must be stored explicitly when they are needed.

Conceptual Background

When a component re-renders, React re-executes the component function and creates a new render scope. Values from earlier renders are not retained unless they are stored in a persistent container.

The useRef hook provides persistence across renders. Its .current property survives re-renders and can be updated without triggering additional renders.

Using useRef to Track the Previous Value

The recommended approach is to store the current value in a ref after each render. During the next render cycle, the ref still contains the previous value.

import { useEffect, useRef, useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  const previousCountRef = useRef();

  useEffect(() => {
    previousCountRef.current = count;
  }, [count]);

  const previousCount = previousCountRef.current;

  return (
    <div>
      <p>Current: {count}</p>
      <p>Previous: {previousCount}</p>
      <button onClick={() => setCount((c) => c + 1)}>Increase</button>
    </div>
  );
}

How the Code Works

  1. useRef creates a persistent container.

  2. After rendering, useEffect updates the ref with the current value.

  3. On the next render, the ref still holds the value from the previous render.

  4. The component can safely compare current and previous values.

This method avoids unnecessary re-renders and maintains predictable behavior.

Important Considerations

Initial render behavior
On the first render, the previous value is undefined because no earlier render exists.

Avoid storing previous values in state
Using state for this purpose introduces unnecessary renders and may create update loops.

Update the ref inside useEffect
Updating the ref during rendering would overwrite the previous value before it can be compared.

Practical Use Cases

Tracking previous values is useful when:

  • determining whether a value increased or decreased

  • executing logic only when specific changes occur

  • triggering animations based on value transitions

  • optimizing performance through value comparison

  • logging changes for analytics or debugging