# usePrevious

A hook that remembers the value from before the most recent change.

## Installation

```bash
npx shadcn@latest add https://mwui.vercel.app/r/use-previous.json
```

[Registry JSON](https://mwui.vercel.app/r/use-previous.json)

## Preview

```tsx
import * as React from "react";

import { Button } from "@/components/ui/button";

import { usePrevious } from "@/hooks/use-previous";

export function Preview() {
  const [value, setValue] = React.useState(12);
  const [unrelated, setUnrelated] = React.useState(0);
  const previous = usePrevious(value);

  const direction = previous === undefined ? "—" : value > previous ? "up" : "down";

  return (
    <div className="flex w-full max-w-sm flex-col gap-4 text-sm">
      <div className="grid grid-cols-3 gap-2 rounded-lg border border-border p-3 text-center">
        <div>
          <p className="text-xs text-muted-foreground">Previous</p>
          <p className="font-mono text-lg tabular-nums">{previous ?? "—"}</p>
        </div>
        <div>
          <p className="text-xs text-muted-foreground">Current</p>
          <p className="font-mono text-lg tabular-nums">{value}</p>
        </div>
        <div>
          <p className="text-xs text-muted-foreground">Direction</p>
          <p className="font-mono text-lg">{direction}</p>
        </div>
      </div>

      <div className="flex flex-wrap gap-2">
        <Button size="sm" variant="outline" onClick={() => setValue((n) => n - 3)}>
          Decrease
        </Button>
        <Button size="sm" variant="outline" onClick={() => setValue((n) => n + 3)}>
          Increase
        </Button>
        <Button size="sm" variant="ghost" onClick={() => setUnrelated((n) => n + 1)}>
          Re-render only ({unrelated})
        </Button>
      </div>

      <p className="text-xs text-muted-foreground">
        Re-rendering without changing the value leaves the previous value untouched.
      </p>
    </div>
  );
}
```


## Source

### hooks/use-previous.ts

```ts
"use client";

import * as React from "react";

function usePrevious<T>(value: T, isEqual: (a: T, b: T) => boolean = Object.is): T | undefined {
  const [current, setCurrent] = React.useState(value);
  const [previous, setPrevious] = React.useState<T | undefined>(undefined);

  if (!isEqual(current, value)) {
    setPrevious(current);
    setCurrent(value);
  }

  return previous;
}

export { usePrevious };
```



## Usage

Useful whenever a render needs to know where a value came from: animating a number in the direction
it moved, highlighting a row that just changed, or firing a transition only on the edge.

```tsx
import { usePrevious } from "@/hooks/use-previous";

function Score({ value }: { value: number }) {
  const previous = usePrevious(value);
  const direction = previous === undefined ? "flat" : value > previous ? "up" : "down";

  return <span data-direction={direction}>{value}</span>;
}
```

## The value it actually returns

The common `useRef` + `useEffect` implementation returns "the value at the last commit", which
quietly becomes the *current* value as soon as the component re-renders for an unrelated reason —
a parent update, a sibling state change. That makes it unreliable exactly when you compare against
it in render.

This version stores the previous value in state and updates it during render, the pattern React
documents for deriving state from props. It returns the value from **before the last change**, and
holds that value steady across re-renders that did not change the input.

```tsx
const previous = usePrevious(value);
// value: 1 → 1 → 2 → 2 → 2
// previous: undefined → undefined → 1 → 1 → 1
```

`undefined` on the first render means there is no previous value yet — not that the previous value
was `undefined`.

## Comparison

Objects and arrays rebuilt each render would register as a change under the default `Object.is`.
Pass a comparator:

```tsx
const previousRange = usePrevious(range, (a, b) => a.start === b.start && a.end === b.end);
```

