Browse Source
feat: tanstack query demos (#4276)
feat: tanstack query demos (#4276)
* chore(@vben/request): add axios-retry * feat: error retry * feat: paginated queries * feat: infinite queries * chore: update * chore: update * fix: ci error * chore: update * chore: remove axios-retry * chore: update deps * chore: update deps * chore: update deps * chore: update pnpm.lock --------- Co-authored-by: vince <vince292007@gmail.com>pull/4353/head
Li Kui
2 weeks ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 239 additions and 0 deletions
-
1playground/package.json
-
5playground/src/bootstrap.ts
-
9playground/src/router/routes/modules/demos.ts
-
25playground/src/views/demos/features/vue-query/index.vue
-
58playground/src/views/demos/features/vue-query/infinite-queries.vue
-
51playground/src/views/demos/features/vue-query/paginated-queries.vue
-
34playground/src/views/demos/features/vue-query/query-retries.vue
-
18playground/src/views/demos/features/vue-query/typing.ts
-
38pnpm-lock.yaml
@ -0,0 +1,25 @@ |
|||
<script setup lang="ts"> |
|||
import { Page } from '@vben/common-ui'; |
|||
|
|||
import { Card } from 'ant-design-vue'; |
|||
|
|||
import InfiniteQueries from './infinite-queries.vue'; |
|||
import PaginatedQueries from './paginated-queries.vue'; |
|||
import QueryRetries from './query-retries.vue'; |
|||
</script> |
|||
|
|||
<template> |
|||
<Page title="Vue Query示例"> |
|||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2"> |
|||
<Card title="分页查询"> |
|||
<PaginatedQueries /> |
|||
</Card> |
|||
<Card title="无限滚动"> |
|||
<InfiniteQueries class="h-[300px] overflow-auto" /> |
|||
</Card> |
|||
<Card title="错误重试"> |
|||
<QueryRetries /> |
|||
</Card> |
|||
</div> |
|||
</Page> |
|||
</template> |
@ -0,0 +1,58 @@ |
|||
<script setup lang="ts"> |
|||
import type { IProducts } from './typing'; |
|||
|
|||
import { useInfiniteQuery } from '@tanstack/vue-query'; |
|||
import { Button } from 'ant-design-vue'; |
|||
|
|||
const LIMIT = 10; |
|||
const fetchProducts = async ({ pageParam = 0 }): Promise<IProducts> => { |
|||
const res = await fetch( |
|||
`https://dummyjson.com/products?limit=${LIMIT}&skip=${pageParam * LIMIT}`, |
|||
); |
|||
return res.json(); |
|||
}; |
|||
|
|||
const { |
|||
data, |
|||
error, |
|||
fetchNextPage, |
|||
hasNextPage, |
|||
isError, |
|||
isFetching, |
|||
isFetchingNextPage, |
|||
isPending, |
|||
} = useInfiniteQuery({ |
|||
getNextPageParam: (current, allPages) => { |
|||
const nextPage = allPages.length + 1; |
|||
const lastPage = current.skip + current.limit; |
|||
if (lastPage === current.total) return; |
|||
return nextPage; |
|||
}, |
|||
initialPageParam: 0, |
|||
queryFn: fetchProducts, |
|||
queryKey: ['products'], |
|||
}); |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<span v-if="isPending">加载...</span> |
|||
<span v-else-if="isError">出错了: {{ error }}</span> |
|||
<div v-else-if="data"> |
|||
<span v-if="isFetching && !isFetchingNextPage">Fetching...</span> |
|||
<ul v-for="(group, index) in data.pages" :key="index"> |
|||
<li v-for="product in group.products" :key="product.id"> |
|||
{{ product.title }} |
|||
</li> |
|||
</ul> |
|||
<Button |
|||
:disabled="!hasNextPage || isFetchingNextPage" |
|||
@click="() => fetchNextPage()" |
|||
> |
|||
<span v-if="isFetchingNextPage">加载中...</span> |
|||
<span v-else-if="hasNextPage">加载更多</span> |
|||
<span v-else>没有更多了</span> |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
</template> |
@ -0,0 +1,51 @@ |
|||
<script setup lang="ts"> |
|||
import type { IProducts } from './typing'; |
|||
|
|||
import { type Ref, ref } from 'vue'; |
|||
|
|||
import { keepPreviousData, useQuery } from '@tanstack/vue-query'; |
|||
import { Button } from 'ant-design-vue'; |
|||
|
|||
const LIMIT = 10; |
|||
const fetcher = async (page: Ref<number>): Promise<IProducts> => { |
|||
const res = await fetch( |
|||
`https://dummyjson.com/products?limit=${LIMIT}&skip=${(page.value - 1) * LIMIT}`, |
|||
); |
|||
return res.json(); |
|||
}; |
|||
|
|||
const page = ref(1); |
|||
const { data, error, isError, isPending, isPlaceholderData } = useQuery({ |
|||
// The data from the last successful fetch is available while new data is being requested. |
|||
placeholderData: keepPreviousData, |
|||
queryFn: () => fetcher(page), |
|||
queryKey: ['products', page], |
|||
}); |
|||
const prevPage = () => { |
|||
page.value = Math.max(page.value - 1, 1); |
|||
}; |
|||
const nextPage = () => { |
|||
if (!isPlaceholderData.value) { |
|||
page.value = page.value + 1; |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="flex gap-4"> |
|||
<Button size="small" @click="prevPage">上一页</Button> |
|||
<p>当前页: {{ page }}</p> |
|||
<Button size="small" @click="nextPage">下一页</Button> |
|||
</div> |
|||
<div class="p-4"> |
|||
<div v-if="isPending">加载中...</div> |
|||
<div v-else-if="isError">出错了: {{ error }}</div> |
|||
<div v-else-if="data"> |
|||
<ul> |
|||
<li v-for="item in data.products" :key="item.id"> |
|||
{{ item.title }} |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</template> |
@ -0,0 +1,34 @@ |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { useQuery } from '@tanstack/vue-query'; |
|||
import { Button } from 'ant-design-vue'; |
|||
|
|||
const count = ref(-1); |
|||
async function fetchApi() { |
|||
count.value += 1; |
|||
return new Promise((_resolve, reject) => { |
|||
setTimeout(() => { |
|||
reject(new Error('something went wrong!')); |
|||
}, 1000); |
|||
}); |
|||
} |
|||
|
|||
const { error, isFetching, refetch } = useQuery({ |
|||
enabled: false, // Disable automatic refetching when the query mounts |
|||
queryFn: fetchApi, |
|||
queryKey: ['queryKey'], |
|||
retry: 3, // Will retry failed requests 3 times before displaying an error |
|||
}); |
|||
|
|||
const onClick = async () => { |
|||
count.value = -1; |
|||
await refetch(); |
|||
}; |
|||
</script> |
|||
|
|||
<template> |
|||
<Button :loading="isFetching" @click="onClick"> 发起错误重试 </Button> |
|||
<p v-if="count > 0" class="my-3">重试次数{{ count }}</p> |
|||
<p>{{ error }}</p> |
|||
</template> |
@ -0,0 +1,18 @@ |
|||
export interface IProducts { |
|||
limit: number; |
|||
products: { |
|||
brand: string; |
|||
category: string; |
|||
description: string; |
|||
discountPercentage: string; |
|||
id: string; |
|||
images: string[]; |
|||
price: string; |
|||
rating: string; |
|||
stock: string; |
|||
thumbnail: string; |
|||
title: string; |
|||
}[]; |
|||
skip: number; |
|||
total: number; |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue