Skip to content

Instantly share code, notes, and snippets.

@itzaks
Created December 5, 2022 12:37
Show Gist options
  • Select an option

  • Save itzaks/3ef8a8003abde0c9d72a19cccfd7d454 to your computer and use it in GitHub Desktop.

Select an option

Save itzaks/3ef8a8003abde0c9d72a19cccfd7d454 to your computer and use it in GitHub Desktop.
useAsyncState composable for fetching asyncdata in composables
import { Ref } from "vue"
interface AsyncStateOptions<T, O> {
transform?: (input: T) => O
}
interface AsyncStateReturnType<T> {
execute: () => Promise<void>,
refresh: () => Promise<void>,
pending: Ref<boolean>,
data: Ref<T>
}
export function useAsyncState<T, O>(key: string, fetchData: () => Promise<T>, options: AsyncStateOptions<T, O>): AsyncStateReturnType<O>
export function useAsyncState<T>(key: string, fetchData: () => Promise<T>): AsyncStateReturnType<T>
export function useAsyncState<T extends O, O>(key: string, fetchData: () => Promise<T>, options?: AsyncStateOptions<T, O>): AsyncStateReturnType<O> {
const data = useState<O | null>(key, () => null)
const pending = useState(key + '-pending', () => false)
const defaultTransform = (data: T) => data
const transform = options?.transform ?? defaultTransform
const fetchNewData = async () => {
pending.value = true
const response = await fetchData()
data.value = transform(response)
pending.value = false
}
const execute = async () => {
if (pending.value || data.value)
return
await fetchNewData()
return
}
const refresh = async () =>
await fetchNewData()
return {
execute,
refresh,
pending,
data
}
}
@itzaks
Copy link
Author

itzaks commented Dec 5, 2022

Example usage

Create a reusable composable:

export const useUserPosts = () => 
 useAsyncState('user-posts', () => GqlUserPosts(), {
    transform: (data) => transformPost(data)
  })
}

Fetch the data from the components (eg pages/index.vue):

<script lang="ts" setup>
const {execute: initialFetch} = useUserPosts()
await initialFetch()
</script>

Use the data and refresh it in a composable:

export const useBlog = () => {
  const {data: userPosts, refresh: refreshUserPosts} = useUserPosts()
  ....
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment