Skip to content

Instantly share code, notes, and snippets.

@wobsoriano
Last active September 6, 2021 12:04
Show Gist options
  • Save wobsoriano/c9954fdf3a49c2314475c747d201d31b to your computer and use it in GitHub Desktop.
Save wobsoriano/c9954fdf3a49c2314475c747d201d31b to your computer and use it in GitHub Desktop.
useInfiniteQuery example with Vue Query and Rick and Morty API
export async function getCharacters(page: number): Promise<Response> {
const response = await fetch('https://rickandmortyapi.com/api/character?page=' + page)
const characters = (await response.json())
return characters;
}
export interface Response {
info: {
count: number
pages: number
next: string
prev: any
}
results: Character[]
}
export interface Character {
id: number
name: string
status: string
species: string
type: string
gender: string
origin: {
name: string
url: string
}
location: {
name: string
url: string
}
image: string
episode: string[]
url: string
created: string
}
<template>
<div>
<h1>Rick and Morty Characters</h1>
<button @click="refetch()" :disabled="isFetching">{{ isFetching ? 'Refetching...' : 'Refetch' }}</button>
<div v-if="isLoading">loading...</div>
<div v-else>
<ul>
<li v-for="char in characters" :key="char.id">
{{ char.name }} - {{ char.status }}
</li>
</ul>
</div>
<button v-show="hasNextPage" @click="fetchNextPage()">{{ isFetchingNextPage ? 'Fetching next page...' : 'Fetch next page' }}</button>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useInfiniteQuery } from 'vue-query'
import { getCharacters, Response, Character } from './api.ts'
const {
data,
isLoading,
refetch,
isFetching,
hasNextPage,
fetchNextPage,
isFetchingNextPage
} = useInfiniteQuery(['characters'], ({ pageParam = 1 }) => getCharacters(pageParam), {
getNextPageParam: (lastPage) => {
const nextUrl = lastPage.info.next
if (nextUrl) {
// Return next page number
return Number(nextUrl.charAt(nextUrl.length - 1))
}
// Return false means no next page
return false
}
})
const characters = computed<Character[]>(() => {
return data.value!.pages.flat().map((char) => {
return char.results
}).flat()
})
</script>
@hoangvu12
Copy link

image
Can I use a page state? My API response doesn't return next page.
Thank you :)

If you still plan on using page state, might be better if you wrap the whole thing to a reactive

const page = ref(1)

const opts = reactive({
    queryKey: ['home', { page: page.value }],
    queryFn: () => HomeQuery(page.value),
    getNextPageParam() {
        page.value += 1
        return page.value
    }
})

const {} = useInfiniteQuery(opts)

Oh yea that's look good, I might try this one instead. Thank you

@wobsoriano
Copy link
Author

Also I think you should do the incrementing part after a successful fetch:

const page = ref(1)

const opts = reactive({
    queryKey: ['home', { page: page.value }],
    queryFn: () => {
      return HomeQuery(page.value)
      .then((data) => {
        page.value += 1
        return data
      })
    },
    getNextPageParam() {
        return page.value
    }
})

const {} = useInfiniteQuery(opts)

Not sure, but that's how I think it should be

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