Skip to content

Commit

Permalink
Is loading (#316)
Browse files Browse the repository at this point in the history
* feat(return) add isLoading return value (#208)

* feat(return) unset isLoading in cases not covered by tests (#208)

---------

Co-authored-by: Adam DeHaven <[email protected]>
  • Loading branch information
ivos and adamdehaven authored Jan 21, 2025
1 parent af1588b commit 092dbe2
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface IResponse<Data = any, Error = any> {
data: Ref<Data | undefined>
error: Ref<Error | undefined>
isValidating: Ref<boolean>
isLoading: Ref<boolean>
mutate: (data?: fetcherFn<Data>, opts?: revalidateOptions) => Promise<void>
}

Expand Down
10 changes: 9 additions & 1 deletion src/use-swrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ import webPreset from './lib/web-preset'
import SWRVCache from './cache'
import { IConfig, IKey, IResponse, fetcherFn, revalidateOptions } from './types'

type StateRef<Data, Error> = { data: Data, error: Error, isValidating: boolean, revalidate: Function, key: any };
type StateRef<Data, Error> = {
data: Data, error: Error, isValidating: boolean, isLoading: boolean, revalidate: Function, key: any
};

const DATA_CACHE = new SWRVCache<Omit<IResponse, 'mutate'>>()
const REF_CACHE = new SWRVCache<StateRef<any, any>[]>()
Expand Down Expand Up @@ -131,6 +133,7 @@ const mutate = async <Data>(key: string, res: Promise<Data> | Data, cache = DATA
}
r.error = newData.error
r.isValidating = newData.isValidating
r.isLoading = newData.isValidating

const isLast = idx === refs.length - 1
if (!isLast) {
Expand Down Expand Up @@ -228,6 +231,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
data: undefined,
error: undefined,
isValidating: true,
isLoading: true,
key: null
}) as StateRef<Data, Error>
}
Expand All @@ -244,6 +248,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
const newData = cacheItem && cacheItem.data

stateRef.isValidating = true
stateRef.isLoading = !newData
if (newData) {
stateRef.data = newData.data
stateRef.error = newData.error
Expand All @@ -256,6 +261,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
(opts?.forceRevalidate !== undefined && !opts?.forceRevalidate)
) {
stateRef.isValidating = false
stateRef.isLoading = false
return
}

Expand All @@ -267,6 +273,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {

if (!shouldRevalidate) {
stateRef.isValidating = false
stateRef.isLoading = false
return
}
}
Expand All @@ -282,6 +289,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
await mutate(keyVal, promiseFromCache.data, config.cache, ttl)
}
stateRef.isValidating = false
stateRef.isLoading = false
PROMISES_CACHE.delete(keyVal)
if (stateRef.error !== undefined) {
const shouldRetryOnError = !unmounted && config.shouldRetryOnError && (opts ? opts.shouldRetryOnError : true)
Expand Down
71 changes: 71 additions & 0 deletions tests/use-swrv.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,77 @@ describe('useSWRV - loading', () => {

expect(wrapper.text()).toBe(':ready')
})

it('should indicate cached data from another key with isLoading false', async () => {
const key = ref(1)
const wrapper = mount(defineComponent({
template: `<div>data: {{ String(data) }}, isValidating: {{ isValidating }}, isLoading: {{ isLoading }}</div>
<button id="inc" v-on:click="inc"/><button id="dec" v-on:click="dec"/>`,
setup () {
const { data, isValidating, isLoading } = useSWRV(() => 'key-' + key.value, async () => {
await loadData()
return 'data-' + key.value
}, { dedupingInterval: 0 })

const inc = () => {
key.value++
}
const dec = () => {
key.value--
}

return { inc, dec, data, isValidating, isLoading }
}
}))

// key 1
// first load ever, cache empty, no data => isLoading true
expect(wrapper.text()).toBe('data: undefined, isValidating: true, isLoading: true')
timeout(100)
await tick(2)
// key-1 data loaded
expect(wrapper.text()).toBe('data: data-1, isValidating: false, isLoading: false')

// key: 1 -> 2
// first load for a key, key cache empty, data from previous key => isLoading true
wrapper.find('#inc').trigger('click')
await tick(2)
expect(wrapper.text()).toBe('data: data-1, isValidating: true, isLoading: true')
timeout(100)
await tick(2)
// data loaded
expect(wrapper.text()).toBe('data: data-2, isValidating: false, isLoading: false')

// key: 2 -> 1
// next load for a key, data from key cache => isLoading false
wrapper.find('#dec').trigger('click')
await tick(2)
expect(wrapper.text()).toBe('data: data-1, isValidating: true, isLoading: false')
timeout(100)
await tick(2)
// data loaded
expect(wrapper.text()).toBe('data: data-1, isValidating: false, isLoading: false')

// key: 1 -> 2
// next load for a key, data from key cache => isLoading false
wrapper.find('#inc').trigger('click')
await tick(2)
expect(wrapper.text()).toBe('data: data-2, isValidating: true, isLoading: false')
timeout(100)
await tick(2)
// data loaded
expect(wrapper.text()).toBe('data: data-2, isValidating: false, isLoading: false')

// key: 2 -> 3
// first load for a key, key cache empty, data from previous key => isLoading true
wrapper.find('#inc').trigger('click')
await tick(2)
expect(wrapper.text()).toBe('data: data-2, isValidating: true, isLoading: true')
timeout(100)
await tick(2)
// data loaded
expect(wrapper.text()).toBe('data: data-3, isValidating: false, isLoading: false')
})
})

describe('useSWRV - mutate', () => {
Expand Down

0 comments on commit 092dbe2

Please sign in to comment.