Vize

use-previous

Track the value a reactive source held before its latest change.

Package @vizejs/composable/use-previous
Own the source vize lib pull composable:use-previous
Runtime exports usePrevious
Gzip budget 1024 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

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

Try it

Show how a ticket price moved

Compare a value with the one it replaced to describe a change, without keeping your own history.

Open the interactive example

What to observe: Before any edit there is no earlier price. Change 120 to 150 to see Up 30 from 120, then to 90 to see Down 60 from 150. Entering the same price again reports it as unchanged.

usePrevious returns a readonly ref that holds the value the source had before its last change, starting as undefined unless you pass an initial value. It updates synchronously, so the comparison is ready in the same render.

Compare the initial and interacted states
Show how a ticket price moved: initial state
Initial state
Show how a ticket price moved: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { computed, ref } from "vue";
import { usePrevious } from "@vizejs/composable/use-previous";

const price = ref(120);
const previous = usePrevious(price);
const change = computed(() => {
  if (previous.value === undefined) return "No earlier price yet.";
  const delta = price.value - previous.value;
  if (delta === 0) return `Unchanged from ${previous.value}.`;
  return `${delta > 0 ? "Up" : "Down"} ${Math.abs(delta)} from ${previous.value}.`;
});
</script>

<template>
  <div class="composable-example">
    <p>Show how a ticket price moved since the last change.</p>
    <label>
      Ticket price
      <input v-model.number="price" type="number" min="0" step="10" />
    </label>
    <output aria-live="polite">{{ change }}</output>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
usePrevious state experimental safe stable none web, server, worker, native, desktop, terminal — —

API

usePrevious

Track the value a reactive source held before its latest change. The semantics are precise and arity-based: - Without an initial argument the ref holds undefined until the source changes for the first time. - With an initial argument (including an explicit undefined when Value allows it) the ref holds that value until the first change, and the return type never widens with undefined. - Every synchronous write is observed (flush: "sync"), so a sequence of writes in one tick shifts the previous value step by step instead of collapsing into one batch. - Writes whose value is Object.is-equal to the current value do not count as changes, matching Vue's own change detection. - Tracking is shallow: reassignments are observed, in-place mutations of object values are not. Safe during server rendering: no browser globals are read and no timers start. The underlying watcher is bound to the current reactive scope and stops with it; call inside an active scope, or the watcher lives as long as the source. A plain non-reactive source never changes, so the ref stays at its initial value.

function usePrevious<Value>( source: MaybeRefOrGetter<Value>, ): Readonly<ShallowRef<Value | undefined>>
const route = shallowRef("/home");
const previousRoute = usePrevious(route, "/");
route.value = "/settings";
previousRoute.value; // "/home"

usePrevious

function usePrevious<Value>( source: MaybeRefOrGetter<Value>, initial: Value, ): Readonly<ShallowRef<Value>>

usePrevious

function usePrevious<Value>( source: MaybeRefOrGetter<Value>, ...initial: readonly [] | readonly [Value] ): Readonly<ShallowRef<Value | undefined>>