Skip to content

Commit

Permalink
feat(useArrayFindLast): new function (#2471)
Browse files Browse the repository at this point in the history
  • Loading branch information
huynl-96 committed Feb 18, 2023
1 parent 81db660 commit b0ac4fa
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
31 changes: 31 additions & 0 deletions packages/shared/useArrayFindLast/index.md
@@ -0,0 +1,31 @@
---
category: Array
---

# useArrayFindLast

Reactive `Array.findLast`.

## Usage

```js
import { useArrayFindLast } from '@vueuse/core'

const list = [ref(1), ref(-1), ref(2)]
const positive = useArrayFindLast(list, val => val > 0)
// positive.value: 2
```

### Use with reactive array

```js
import { useArrayFindLast } from '@vueuse/core'

const list = reactive([-1, -2])
const positive = useArrayFindLast(list, val => val > 0)
// positive.value: undefined
list.push(10)
// positive.value: 10
list.push(5)
// positive.value: 5
```
37 changes: 37 additions & 0 deletions packages/shared/useArrayFindLast/index.test.ts
@@ -0,0 +1,37 @@
import { reactive, ref } from 'vue-demi'
import { useSetup } from '../../.test'
import { useArrayFindLast } from '../useArrayFindLast'

describe('useArrayFindLast', () => {
it('should be defined', () => {
expect(useArrayFindLast).toBeDefined()
})

it('should find positive', () => {
useSetup(() => {
const item1 = ref(1)
const item2 = ref(2)
const item3 = ref(3)
const positive = useArrayFindLast([item1, item2, item3], val => val > 0)
expect(positive.value).toBe(3)
item3.value = -1
expect(positive.value).toBe(2)
item2.value = -1
expect(positive.value).toBe(1)
item1.value = -1
expect(positive.value).toBe(undefined)
})
})

it('should work with reactive array', () => {
useSetup(() => {
const list = reactive([-1, -2])
const positive = useArrayFindLast(list, val => val > 0)
expect(positive.value).toBe(undefined)
list.push(10)
expect(positive.value).toBe(10)
list.push(5)
expect(positive.value).toBe(5)
})
})
})
40 changes: 40 additions & 0 deletions packages/shared/useArrayFindLast/index.ts
@@ -0,0 +1,40 @@
import type { ComputedRef } from 'vue-demi'
import { computed } from 'vue-demi'
import type { MaybeComputedRef } from '../utils'
import { resolveUnref } from '../resolveUnref'

// Polyfill for node version < 18
function findLast<T>(arr: T[], cb: (element: T, index: number, array: T[]) => boolean): T | undefined {
let index = arr.length
while (index-- > 0) {
if (cb(arr[index], index, arr))
return arr[index]
}
return undefined
}

/**
* Reactive `Array.findLast`
*
* @see https://vueuse.org/useArrayFindLast
* @param {Array} list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns the last element in the array that satisfies the provided testing function. Otherwise, undefined is returned.
*/
export function useArrayFindLast<T>(
list: MaybeComputedRef<MaybeComputedRef<T>[]>,
fn: (element: T, index: number, array: MaybeComputedRef<T>[]) => boolean,
): ComputedRef<T | undefined> {
return computed(() =>
resolveUnref<T | undefined>(
// @ts-expect-error - missing in types
// https://github.com/microsoft/TypeScript/issues/48829
!Array.prototype.findLast
? findLast(resolveUnref(list), (element, index, array) => fn(resolveUnref(element), index, array))
: resolveUnref(list)
// @ts-expect-error - missing in types
.findLast((element, index, array) => fn(resolveUnref(element), index, array)),
),
)
}

0 comments on commit b0ac4fa

Please sign in to comment.