Skip to content

Commit

Permalink
feat(usePrevious): new function
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jan 29, 2023
1 parent 43a8016 commit e101fb8
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/core/usePrevious/index.md
@@ -0,0 +1,23 @@
---
category: Utilities
---

# usePrevious

Holds the previous value of a ref.

## Usage

```ts
import { ref } from 'vue'
import { usePrevious } from '@vueuse/core'

const counter = ref('Hello')
const previous = usePrevious(counter)

console.log(previous.value) // undefined

counter.value = 'World'

console.log(previous.value) // Hello
```
47 changes: 47 additions & 0 deletions packages/core/usePrevious/index.test.ts
@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest'
import { ref } from 'vue-demi'
import { usePrevious } from '.'

describe('usePrevious', () => {
it('works for literals', () => {
const target = ref(1)
const previous = usePrevious(target)

expect(previous.value).toBe(undefined)

target.value = 2

expect(previous.value).toBe(1)

target.value = 10

expect(previous.value).toBe(2)
})

it('works with initial value', () => {
const target = ref('Hello')
const previous = usePrevious(() => target.value, 'initial')

expect(previous.value).toBe('initial')

target.value = 'World'

expect(previous.value).toBe('Hello')
})

it('works with object', () => {
const target = ref<any>({ a: 1 })
const previous = usePrevious(target)

expect(previous.value).toEqual(undefined)

target.value.a = 2

// nested reactiveness is not triggered
expect(previous.value).toEqual(undefined)

target.value = { b: 2 }

expect(previous.value).toEqual({ a: 2 })
})
})
27 changes: 27 additions & 0 deletions packages/core/usePrevious/index.ts
@@ -0,0 +1,27 @@
/* This implementation is original ported from https://github.com/shorwood/pompaute by Stanley Horwood */

import type { Ref } from 'vue-demi'
import { readonly, shallowRef, watch } from 'vue-demi'
import type { MaybeComputedRef } from '@vueuse/shared'
import { resolveRef } from '@vueuse/shared'

/**
* Holds the previous value of a ref.
*
* @see {@link https://vueuse.org/usePrevious}
*/
export function usePrevious<T>(value: MaybeComputedRef<T>): Readonly<Ref<T | undefined>>
export function usePrevious<T>(value: MaybeComputedRef<T>, initialValue: T): Readonly<Ref<T>>
export function usePrevious<T>(value: MaybeComputedRef<T>, initialValue?: T) {
const previous = shallowRef<T | undefined>(initialValue)

watch(
resolveRef(value),
(_, oldValue) => {
previous.value = oldValue
},
{ flush: 'sync' },
)

return readonly(previous)
}

0 comments on commit e101fb8

Please sign in to comment.