Skip to content

Commit fdb7692

Browse files
authored
docs(examples/vue): add 'pagination', 'auto-refetching', 'load-more-infinite-scroll', 'infinite-query-with-max-pages', 'prefetching' and 'optimistic-updates' examples with Nuxt (#12445)
1 parent ff41bb2 commit fdb7692

82 files changed

Lines changed: 7067 additions & 72 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/config.json‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6970,6 +6970,30 @@
69706970
{
69716971
"label": "Batching",
69726972
"to": "framework/vue/examples/batching"
6973+
},
6974+
{
6975+
"label": "Auto Refetching / Polling / Realtime",
6976+
"to": "framework/vue/examples/auto-refetching"
6977+
},
6978+
{
6979+
"label": "Optimistic Updates",
6980+
"to": "framework/vue/examples/optimistic-updates"
6981+
},
6982+
{
6983+
"label": "Pagination",
6984+
"to": "framework/vue/examples/pagination"
6985+
},
6986+
{
6987+
"label": "Load-More & Infinite Scroll",
6988+
"to": "framework/vue/examples/load-more-infinite-scroll"
6989+
},
6990+
{
6991+
"label": "Infinite query with Max pages",
6992+
"to": "framework/vue/examples/infinite-query-with-max-pages"
6993+
},
6994+
{
6995+
"label": "Prefetching",
6996+
"to": "framework/vue/examples/prefetching"
69736997
}
69746998
]
69756999
},
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Nuxt dev/build outputs
2+
.output
3+
.data
4+
.nuxt
5+
.nitro
6+
.cache
7+
dist
8+
9+
# Node dependencies
10+
node_modules
11+
12+
# Logs
13+
logs
14+
*.log
15+
16+
# Misc
17+
.DS_Store
18+
.fleet
19+
.idea
20+
21+
# Local env files
22+
.env
23+
.env.*
24+
!.env.example
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Auto Refetching example
2+
3+
To run this example:
4+
5+
- `npm install` or `yarn` or `pnpm i` or `bun i`
6+
- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
4+
import { VueQueryDevtools } from '@tanstack/vue-query-devtools'
5+
import { todosMutations, todosQueries } from './services/todos/queries'
6+
7+
const queryClient = useQueryClient()
8+
const intervalMs = ref(1000)
9+
const value = ref('')
10+
11+
const { status, data, error, isFetching } = useQuery(() => ({
12+
...todosQueries.list(),
13+
// Refetch the data every second
14+
refetchInterval: intervalMs.value,
15+
}))
16+
17+
const { mutate: addTodo } = useMutation({
18+
...todosMutations.create(),
19+
onSuccess: () =>
20+
queryClient.invalidateQueries({ queryKey: todosQueries.all() }),
21+
})
22+
23+
const { mutate: clearTodos } = useMutation({
24+
...todosMutations.deleteAll(),
25+
onSuccess: () =>
26+
queryClient.invalidateQueries({ queryKey: todosQueries.all() }),
27+
})
28+
29+
const onSubmit = () => {
30+
addTodo(value.value, {
31+
onSuccess: () => {
32+
value.value = ''
33+
},
34+
})
35+
}
36+
</script>
37+
38+
<template>
39+
<h1 v-if="status === 'pending'">Loading...</h1>
40+
<span v-else-if="status === 'error'">Error: {{ error?.message }}</span>
41+
<div v-else>
42+
<h1>Auto Refetch with refetchInterval set to {{ intervalMs }}ms</h1>
43+
<p>
44+
This example is best experienced on your own machine, where you can open
45+
multiple tabs to the same localhost server and see your changes propagate
46+
between the two.
47+
</p>
48+
<label>
49+
Query Interval speed (ms):
50+
<input v-model.number="intervalMs" type="number" step="100" />
51+
{{ ' ' }}
52+
<span
53+
:style="{
54+
display: 'inline-block',
55+
marginLeft: '.5rem',
56+
width: '10px',
57+
height: '10px',
58+
background: isFetching ? 'green' : 'transparent',
59+
transition: !isFetching ? 'all .3s ease' : 'none',
60+
borderRadius: '100%',
61+
transform: 'scale(2)',
62+
}"
63+
/>
64+
</label>
65+
<h2>Todo List</h2>
66+
<form @submit.prevent="onSubmit">
67+
<input v-model="value" placeholder="enter something" />
68+
</form>
69+
<ul>
70+
<li v-for="item in data" :key="item">{{ item }}</li>
71+
</ul>
72+
<div>
73+
<button @click="clearTodos()">Clear All</button>
74+
</div>
75+
<VueQueryDevtools initialIsOpen />
76+
</div>
77+
</template>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {
2+
QueryClient,
3+
VueQueryPlugin,
4+
dehydrate,
5+
hydrate,
6+
} from '@tanstack/vue-query'
7+
import type { DehydratedState } from '@tanstack/vue-query'
8+
9+
export default defineNuxtPlugin((nuxt) => {
10+
const vueQueryState = useState<DehydratedState | null>('vue-query')
11+
12+
const queryClient = new QueryClient()
13+
14+
nuxt.vueApp.use(VueQueryPlugin, { queryClient })
15+
16+
if (import.meta.server) {
17+
nuxt.hooks.hook('app:rendered', () => {
18+
vueQueryState.value = dehydrate(queryClient)
19+
})
20+
}
21+
22+
if (import.meta.client) {
23+
nuxt.hooks.hook('app:created', () => {
24+
if (vueQueryState.value) {
25+
hydrate(queryClient, vueQueryState.value)
26+
}
27+
})
28+
}
29+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const todosAPI = {
2+
getTodos: (): Promise<Array<string>> => $fetch('/api/data'),
3+
createTodo: async (add: string) => {
4+
await $fetch('/api/data', { query: { add } })
5+
},
6+
deleteTodos: async () => {
7+
await $fetch('/api/data', { query: { clear: 1 } })
8+
},
9+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { mutationOptions, queryOptions } from '@tanstack/vue-query'
2+
import { todosAPI } from './api'
3+
4+
export const todosQueries = {
5+
all: () => ['todos'] as const,
6+
list: () =>
7+
queryOptions({
8+
queryKey: [...todosQueries.all(), 'list'] as const,
9+
queryFn: () => todosAPI.getTodos(),
10+
}),
11+
}
12+
13+
export const todosMutations = {
14+
create: () =>
15+
mutationOptions({
16+
mutationFn: (add: string) => todosAPI.createTodo(add),
17+
}),
18+
deleteAll: () =>
19+
mutationOptions({
20+
mutationFn: () => todosAPI.deleteTodos(),
21+
}),
22+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @ts-check
2+
3+
import { tanstackConfig } from '@tanstack/eslint-config'
4+
import pluginQuery from '@tanstack/eslint-plugin-query'
5+
import { defineConfig } from 'eslint/config'
6+
7+
export default defineConfig([
8+
...tanstackConfig,
9+
...pluginQuery.configs['flat/recommended-strict'],
10+
{
11+
languageOptions: {
12+
parserOptions: {
13+
project: false,
14+
projectService: true,
15+
extraFileExtensions: ['.vue'],
16+
},
17+
},
18+
},
19+
])
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// https://nuxt.com/docs/api/configuration/nuxt-config
2+
export default defineNuxtConfig({
3+
compatibilityDate: '2025-07-15',
4+
devtools: { enabled: true },
5+
typescript: {
6+
nodeTsConfig: {
7+
include: ['../eslint.config.js'],
8+
},
9+
},
10+
})
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "@tanstack/query-example-vue-auto-refetching",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"dev": "nuxt dev",
7+
"build": "nuxt build",
8+
"preview": "nuxt preview",
9+
"postinstall": "nuxt prepare",
10+
"test:eslint": "eslint ./app ./server",
11+
"test:types": "nuxt typecheck"
12+
},
13+
"dependencies": {
14+
"@tanstack/vue-query": "^5.105.0",
15+
"@tanstack/vue-query-devtools": "^6.3.6",
16+
"nuxt": "4.6.2",
17+
"vue": "^3.5.44",
18+
"vue-router": "^5.4.0"
19+
},
20+
"devDependencies": {
21+
"@tanstack/eslint-plugin-query": "^5.105.0",
22+
"typescript": "^6.0.3",
23+
"vue-tsc": "^3.3.13"
24+
}
25+
}

0 commit comments

Comments
 (0)