Skip to content

Instantly share code, notes, and snippets.

@darrenjennings
Created January 24, 2020 22:31
Show Gist options
  • Save darrenjennings/d138e89d0ee87a3906e3a5e0f0d9dc03 to your computer and use it in GitHub Desktop.
Save darrenjennings/d138e89d0ee87a3906e3a5e0f0d9dc03 to your computer and use it in GitHub Desktop.
useSWR for Vue hooks
import { Ref, reactive, onMounted, watch, toRefs } from '@vue/composition-api'
// const { data, error } = useSWR('/api/user', fetcher)
export type fetcherFn<Data> = (...args: any) => Data | Promise<Data>
function isDocumentVisible (): boolean {
if (
typeof document !== 'undefined' &&
typeof document.visibilityState !== 'undefined'
) {
return document.visibilityState !== 'hidden'
}
// always assume it's visible
return true
}
export default function useSWR<Data = any, Error = any> (key: string, fn: fetcherFn<any>, config = {
refreshInterval: 3000
}): {
data: Ref<any>
pending: Ref<boolean>
error: Ref<any>
} {
const stateRef = reactive({
data: null,
pending: true,
error: null
})
const revalidate = () => {
fn().then(res => {
stateRef.data = res
}).catch(err => {
stateRef.error = err
}).finally(() => {
stateRef.pending = false
})
}
// set up polling
onMounted(() => {
let timer = null
const tick = async () => {
if (
!stateRef.error &&
isDocumentVisible()
// && isOnline()
) {
// only revalidate when the page is visible
// if API request errored, we stop polling in this round
// and let the error retry function handle it
await revalidate()
}
if (config.refreshInterval) {
timer = setTimeout(tick, config.refreshInterval)
}
}
if (config.refreshInterval) {
timer = setTimeout(tick, config.refreshInterval)
}
return () => {
if (timer) { clearTimeout(timer) }
}
})
const stateRefs = toRefs(stateRef)
revalidate()
return {
...stateRefs
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment