Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(use-swrv): reactive refreshInterval #349

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import LocalStorageCache from './cache/adapters/localStorage'

export type fetcherFn<Data> = (...args: any) => Data | Promise<Data>

type MaybeRef<T> = T | Ref<T>

export interface IConfig<
Data = any,
Fn extends fetcherFn<Data> = fetcherFn<Data>
> {
refreshInterval?: number
refreshInterval?: MaybeRef<number>
cache?: LocalStorageCache | SWRVCache<any>
dedupingInterval?: number
ttl?: number
Expand Down
73 changes: 46 additions & 27 deletions src/use-swrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import {
watch,
ref,
toRefs,
// isRef,
isRef,
onMounted,
onUnmounted,
getCurrentInstance,
isReadonly
isReadonly,
computed
} from 'vue'
import webPreset from './lib/web-preset'
import SWRVCache from './cache'
Expand Down Expand Up @@ -157,6 +158,12 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
let unmounted = false
let isHydrated = false

const refreshInterval = computed(() =>
isRef(config.refreshInterval)
? config.refreshInterval.value
: config.refreshInterval
)

const instance = getCurrentInstance() as any
const vm = instance?.proxy || instance // https://github.com/vuejs/composition-api/pull/520
if (!vm) {
Expand Down Expand Up @@ -300,32 +307,46 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {

const revalidateCall = async () => revalidate(null, { shouldRetryOnError: false })
let timer = null
/**
* Setup polling
*/
onMounted(() => {
const tick = async () => {
// component might un-mount during revalidate, so do not set a new timeout
// if this is the case, but continue to revalidate since promises can't
// be cancelled and new hook instances might rely on promise/data cache or
// from pre-fetch
if (!stateRef.error && config.isOnline()) {
// if API request errored, we stop polling in this round
// and let the error retry function handle it
await revalidate()
} else {
if (timer) {
clearTimeout(timer)
}
}

if (config.refreshInterval && !unmounted) {
timer = setTimeout(tick, config.refreshInterval)
const clearTimer = () => {
timer && clearTimeout(timer)
}

const tick = async () => {
// component might un-mount during revalidate, so do not set a new timeout
// if this is the case, but continue to revalidate since promises can't
// be cancelled and new hook instances might rely on promise/data cache or
// from pre-fetch
if (!stateRef.error && config.isOnline()) {
// if API request errored, we stop polling in this round
// and let the error retry function handle it
await revalidate()
} else {
if (timer) {
clearTimeout(timer)
}
}

if (config.refreshInterval) {
timer = setTimeout(tick, config.refreshInterval)
if (refreshInterval.value && !unmounted) {
timer = setTimeout(tick, refreshInterval.value)
}
}

watch(refreshInterval, (val, oldVal) => {
if (val === oldVal) { return }

clearTimer()
if (val) {
timer = setTimeout(tick, val)
}
})

/**
* Setup polling
*/
onMounted(() => {
if (refreshInterval.value) {
timer = setTimeout(tick, refreshInterval.value)
}
if (config.revalidateOnFocus) {
document.addEventListener('visibilitychange', revalidateCall, false)
Expand All @@ -338,9 +359,7 @@ function useSWRV<Data = any, Error = any> (...args): IResponse<Data, Error> {
*/
onUnmounted(() => {
unmounted = true
if (timer) {
clearTimeout(timer)
}
clearTimer()
if (config.revalidateOnFocus) {
document.removeEventListener('visibilitychange', revalidateCall, false)
window.removeEventListener('focus', revalidateCall, false)
Expand Down
64 changes: 64 additions & 0 deletions tests/use-swrv.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,70 @@ describe('useSWRV - refresh', () => {
expect(wrapper.text()).toEqual('count: 2')
})

it('should stop rerendering when interval is changed to zero', async () => {
let count = 0

const refreshInterval = ref(200)

const wrapper = mount(defineComponent({
template: '<div>count: {{ data }}</div>',
setup () {
return useSWRV('dynamic-1-1', () => count++, {
refreshInterval,
dedupingInterval: 0
})
}
}))

await tick(2)
expect(wrapper.text()).toEqual('count: 0')
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 1')
refreshInterval.value = 0
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 2')
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 2')
})

it('should start rerendering when interval is changed from zero to non-zero', async () => {
let count = 0

const refreshInterval = ref(0)

const wrapper = mount(defineComponent({
template: '<div>count: {{ data }}</div>',
setup () {
return useSWRV('dynamic-1-2', () => count++, {
refreshInterval,
dedupingInterval: 0
})
}
}))

await tick(2)
expect(wrapper.text()).toEqual('count: 0')
timeout(200)
await tick(2)
expect(wrapper.text()).toEqual('count: 0')
refreshInterval.value = 200
timeout(200)
await tick(2)
expect(wrapper.text()).toEqual('count: 0')
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 1')
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 2')
timeout(210)
await tick(2)
expect(wrapper.text()).toEqual('count: 3')
})

it('should dedupe requests combined with intervals - promises', async () => {
advanceTo(new Date())
/**
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"outDir": "./dist",
"types": [
"webpack-env",
"node", "jest"
"node",
"jest"
],
"lib": [
"esnext",
Expand Down