Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/shared/whenever/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ whenever(height, (current, lastHeight) => {
})
```

### Sources Array

Same as `watch`, multiple sources can be passed to check if any of them are true.

```ts
import { whenever } from '@vueuse/core'
// ---cut---
// this
whenever([result, error], () => {
loading.value = false
})

// is equivalent to:
whenever(result, () => {
loading.value = false
})
whenever(error, () => {
loading.value = false
})
```

### Computed

Same as `watch`, you can pass a getter function to calculate on each change.
Expand Down
79 changes: 79 additions & 0 deletions packages/shared/whenever/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,83 @@ describe('whenever', () => {

vm.unmount()
})

it('eagerly callback for array value truthiness', async () => {
// use a component to simulate normal use case
const vm = useSetup(() => {
const number = shallowRef<number | null | undefined>(1)
const str = shallowRef<string | null | undefined>('foo')
const changeNumber = (v: number) => number.value = v
const changeString = (v: string) => str.value = v
const watchCount = shallowRef(0)
const watchNumberValue: Ref<number | null | undefined> = deepRef()
const watchStringValue: Ref<string | null | undefined> = deepRef()

whenever([number, str], ([numberValue, stringValue]) => {
watchCount.value += 1
watchNumberValue.value = numberValue
watchStringValue.value = stringValue

expectType<number>(numberValue!)
expectType<string>(stringValue!)

// @ts-expect-error numberValue should be of type number
expectType<undefined>(numberValue)
// @ts-expect-error numberValue should be of type number
expectType<null>(numberValue)
// @ts-expect-error numberValue should be of type number
expectType<string>(numberValue)

// @ts-expect-error stringValue should be of type string
expectType<undefined>(stringValue)
// @ts-expect-error stringValue should be of type string
expectType<null>(stringValue)
// @ts-expect-error stringValue should be of type string
expectType<number>(stringValue)
})

return {
number,
watchCount,
watchNumberValue,
watchStringValue,
changeNumber,
changeString,
}
})

expect(toValue(vm.watchCount)).toEqual(0)

vm.changeNumber(2)
await nextTick()
expect(toValue(vm.watchCount)).toEqual(1)
expect(toValue(vm.watchNumberValue)).toEqual(2)
expect(toValue(vm.watchStringValue)).toEqual('foo')

vm.changeNumber(0)
await nextTick()
expect(toValue(vm.watchCount)).toEqual(2)
expect(toValue(vm.watchNumberValue)).toEqual(0)
expect(toValue(vm.watchStringValue)).toEqual('foo')

vm.changeString('')
await nextTick()
expect(toValue(vm.watchCount)).toEqual(2)
expect(toValue(vm.watchNumberValue)).toEqual(0)
expect(toValue(vm.watchStringValue)).toEqual('foo')

vm.changeNumber(3)
await nextTick()
expect(toValue(vm.watchCount)).toEqual(3)
expect(toValue(vm.watchNumberValue)).toEqual(3)
expect(toValue(vm.watchStringValue)).toEqual('')

vm.changeString('bar')
await nextTick()
expect(toValue(vm.watchCount)).toEqual(4)
expect(toValue(vm.watchNumberValue)).toEqual(3)
expect(toValue(vm.watchStringValue)).toEqual('bar')

vm.unmount()
})
})
12 changes: 9 additions & 3 deletions packages/shared/whenever/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { WatchCallback, WatchOptions, WatchSource } from 'vue'
import type { WatchCallback, WatchHandle, WatchOptions, WatchSource } from 'vue'
import type { MapOldSources, MapSources } from '../utils'
import { nextTick, watch } from 'vue'

export interface WheneverOptions extends WatchOptions {
Expand All @@ -12,16 +13,21 @@ export interface WheneverOptions extends WatchOptions {
once?: boolean
}

// overloads
export function whenever<T extends Readonly<WatchSource<unknown>[]>>(sources: readonly [...T] | T, cb: WatchCallback<MapSources<T>, MapOldSources<T, true>>, options?: WheneverOptions): WatchHandle
export function whenever<T>(source: WatchSource<T | false | null | undefined>, cb: WatchCallback<T>, options?: WheneverOptions): WatchHandle
export function whenever<T extends object>(source: T, cb: WatchCallback<T>, options?: WheneverOptions): WatchHandle

/**
* Shorthand for watching value to be truthy
*
* @see https://vueuse.org/whenever
*/
export function whenever<T>(source: WatchSource<T | false | null | undefined>, cb: WatchCallback<T>, options?: WheneverOptions) {
export function whenever(source: any, cb: WatchCallback, options?: WheneverOptions) {
const stop = watch(
source,
(v, ov, onInvalidate) => {
if (v) {
if (Array.isArray(v) ? v.some(Boolean) : v) {
if (options?.once)
nextTick(() => stop())
cb(v, ov, onInvalidate)
Expand Down