snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

9
examples/vue/2.6-basic/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,6 @@
# 2.6 Basic example
To run this example:
- `npm install` or `yarn` or `pnpm i` or `bun i`
- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Query Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,22 @@
{
"name": "@tanstack/query-example-vue-2.6-basic",
"private": true,
"type": "module",
"scripts": {
"postinstall": "vue-demi-switch 2",
"dev": "vite",
"_build": "vite build",
"_preview": "vite preview"
},
"dependencies": {
"@tanstack/vue-query": "^5.90.2",
"@vue/composition-api": "1.7.2",
"vue": "2.6.14",
"vue-template-compiler": "2.6.14"
},
"devDependencies": {
"typescript": "5.8.3",
"vite": "^4.5.14",
"vite-plugin-vue2": "2.0.3"
}
}

View File

@@ -0,0 +1,45 @@
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api'
import Posts from './Posts.vue'
import Post from './Post.vue'
export default defineComponent({
name: 'App',
components: { Posts, Post },
setup() {
const visitedPosts = ref(new Set())
const isVisited = (id: number) => visitedPosts.value.has(id)
const postId = ref(-1)
const setPostId = (id: number) => {
visitedPosts.value.add(id)
postId.value = id
}
return {
isVisited,
postId,
setPostId,
}
},
})
</script>
<template>
<div>
<h1>Vue Query - Basic</h1>
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click
on any posts you have already visited again, you will see them load
instantly and background refresh right before your eyes!
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
<Post v-if="postId > -1" :postId="postId" @setPostId="setPostId" />
<Posts v-else :isVisited="isVisited" @setPostId="setPostId" />
</div>
</template>

View File

@@ -0,0 +1,53 @@
<script lang="ts">
import { defineComponent, toRaw } from '@vue/composition-api'
import { useQuery } from '@tanstack/vue-query'
import { Post } from './types'
const fetcher = async (id: number): Promise<Post> =>
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(
(response) => response.json(),
)
export default defineComponent({
name: 'PostDetails',
props: {
postId: {
type: Number,
required: true,
},
},
emits: ['setPostId'],
setup(props) {
const { isPending, isError, isFetching, data, error } = useQuery({
queryKey: ['post', () => props.postId],
queryFn: () => fetcher(props.postId),
})
return { isPending, isError, isFetching, data, error }
},
})
</script>
<template>
<div>
<h1>Post {{ postId }}</h1>
<a @click="$emit('setPostId', -1)" href="#"> Back </a>
<div v-if="isPending" class="update">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<h1>{{ data.title }}</h1>
<div>
<p>{{ data.body }}</p>
</div>
<div v-if="isFetching" class="update">Background Updating...</div>
</div>
</div>
</template>
<style scoped>
.update {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,57 @@
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
import { useQuery } from '@tanstack/vue-query'
import type { Post } from './types'
const fetcher = async (): Promise<Post[]> =>
await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>
response.json(),
)
export default defineComponent({
name: 'PostsList',
props: {
isVisited: {
type: Function,
required: true,
},
},
emits: ['setPostId'],
setup() {
const { isPending, isError, isFetching, data, error, refetch } = useQuery({
queryKey: ['posts'],
queryFn: fetcher,
})
return { isPending, isError, isFetching, data, error, refetch }
},
})
</script>
<template>
<div>
<h1>Posts</h1>
<div v-if="isPending">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<ul>
<li v-for="item in data" :key="item.id">
<a
@click="$emit('setPostId', item.id)"
href="#"
:class="{ visited: isVisited(item.id) }"
>{{ item.title }}</a
>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
.visited {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,14 @@
import Vue from 'vue'
import VueCompositionApi, { createApp, h } from '@vue/composition-api'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'
Vue.use(VueCompositionApi)
Vue.use(VueQueryPlugin)
createApp({
render() {
return h(App)
},
}).mount('#app')

View File

@@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

6
examples/vue/2.6-basic/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export interface Post {
userId: number
id: number
title: string
body: string
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}

View File

@@ -0,0 +1,6 @@
import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
export default defineConfig({
plugins: [createVuePlugin()],
})

9
examples/vue/2.7-basic/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,6 @@
# 2.7 Basic example
To run this example:
- `npm install` or `yarn` or `pnpm i`
- `npm run dev` or `yarn dev` or `pnpm dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Query Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,21 @@
{
"name": "@tanstack/query-example-vue-2.7-basic",
"private": true,
"scripts": {
"postinstall": "vue-demi-switch 2.7",
"dev": "vite",
"_build": "vite build",
"_build:dev": "vite build -m development",
"_serve": "vite preview"
},
"dependencies": {
"@tanstack/vue-query": "^5.90.2",
"vue": "2.7.16",
"vue-template-compiler": "2.7.16"
},
"devDependencies": {
"typescript": "5.8.3",
"vite": "^4.5.14",
"vite-plugin-vue2": "2.0.3"
}
}

View File

@@ -0,0 +1,45 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Posts from './Posts.vue'
import Post from './Post.vue'
export default defineComponent({
name: 'App',
components: { Posts, Post },
setup() {
const visitedPosts = ref(new Set())
const isVisited = (id: number) => visitedPosts.value.has(id)
const postId = ref(-1)
const setPostId = (id: number) => {
visitedPosts.value.add(id)
postId.value = id
}
return {
isVisited,
postId,
setPostId,
}
},
})
</script>
<template>
<div>
<h1>Vue Query - Basic</h1>
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click
on any posts you have already visited again, you will see them load
instantly and background refresh right before your eyes!
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
<Post v-if="postId > -1" :postId="postId" @setPostId="setPostId" />
<Posts v-else :isVisited="isVisited" @setPostId="setPostId" />
</div>
</template>

View File

@@ -0,0 +1,53 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Post } from './types'
const fetcher = async (id: number): Promise<Post> =>
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(
(response) => response.json(),
)
export default defineComponent({
name: 'PostDetails',
props: {
postId: {
type: Number,
required: true,
},
},
emits: ['setPostId'],
setup(props) {
const { isPending, isError, isFetching, data, error } = useQuery({
queryKey: ['post', () => props.postId],
queryFn: () => fetcher(props.postId),
})
return { isPending, isError, isFetching, data, error }
},
})
</script>
<template>
<div>
<h1>Post {{ postId }}</h1>
<a @click="$emit('setPostId', -1)" href="#"> Back </a>
<div v-if="isPending" class="update">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<h1>{{ data.title }}</h1>
<div>
<p>{{ data.body }}</p>
</div>
<div v-if="isFetching" class="update">Background Updating...</div>
</div>
</div>
</template>
<style scoped>
.update {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,57 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import type { Post } from './types'
const fetcher = async (): Promise<Post[]> =>
await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>
response.json(),
)
export default defineComponent({
name: 'PostsList',
props: {
isVisited: {
type: Function,
required: true,
},
},
emits: ['setPostId'],
setup() {
const { isPending, isError, isFetching, data, error, refetch } = useQuery({
queryKey: ['posts'],
queryFn: fetcher,
})
return { isPending, isError, isFetching, data, error, refetch }
},
})
</script>
<template>
<div>
<h1>Posts</h1>
<div v-if="isPending">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<ul>
<li v-for="item in data" :key="item.id">
<a
@click="$emit('setPostId', item.id)"
href="#"
:class="{ visited: isVisited(item.id) }"
>{{ item.title }}</a
>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
.visited {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,14 @@
import Vue, { h } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'
Vue.use(VueQueryPlugin)
var app = new Vue({
el: '#app',
render: () => {
return h(App)
},
})

View File

@@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

6
examples/vue/2.7-basic/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export interface Post {
userId: number
id: number
title: string
body: string
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"]
},
"include": ["src/*.ts", "src/*.d.ts", "src/*.vue"]
}

View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [createVuePlugin()],
})

9
examples/vue/basic/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,6 @@
# Basic example
To run this example:
- `npm install` or `yarn` or `pnpm i` or `bun i`
- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Query Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,20 @@
{
"name": "@tanstack/query-example-vue-basic",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@tanstack/vue-query": "^5.102.8",
"@tanstack/vue-query-devtools": "^6.1.48",
"vue": "^3.4.27"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"typescript": "5.8.3",
"vite": "^6.4.1"
}
}

View File

@@ -0,0 +1,45 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { VueQueryDevtools } from '@tanstack/vue-query-devtools'
import Posts from './Posts.vue'
import Post from './Post.vue'
export default defineComponent({
name: 'App',
components: { Posts, Post, VueQueryDevtools },
setup() {
const visitedPosts = ref(new Set())
const isVisited = (id: number) => visitedPosts.value.has(id)
const postId = ref(-1)
const setPostId = (id: number) => {
visitedPosts.value.add(id)
postId.value = id
}
return {
isVisited,
postId,
setPostId,
}
},
})
</script>
<template>
<h1>Vue Query - Basic</h1>
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click
on any posts you have already visited again, you will see them load
instantly and background refresh right before your eyes!
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
<Post v-if="postId > -1" :postId="postId" @setPostId="setPostId" />
<Posts v-else :isVisited="isVisited" @setPostId="setPostId" />
<VueQueryDevtools />
</template>

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Post } from './types'
const fetcher = async (id: number): Promise<Post> =>
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(
(response) => response.json(),
)
export default defineComponent({
name: 'PostDetails',
props: {
postId: {
type: Number,
required: true,
},
},
emits: ['setPostId'],
setup(props) {
const { isPending, isError, isFetching, data, error } = useQuery({
queryKey: ['post', () => props.postId],
queryFn: () => fetcher(props.postId),
})
return { isPending, isError, isFetching, data, error }
},
})
</script>
<template>
<h1>Post {{ postId }}</h1>
<a @click="$emit('setPostId', -1)" href="#"> Back </a>
<div v-if="isPending" class="update">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<h1>{{ data.title }}</h1>
<div>
<p>{{ data.body }}</p>
</div>
<div v-if="isFetching" class="update">Background Updating...</div>
</div>
</template>
<style scoped>
.update {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,55 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import type { Post } from './types'
const fetcher = async (): Promise<Post[]> =>
await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>
response.json(),
)
export default defineComponent({
name: 'PostsList',
props: {
isVisited: {
type: Function,
required: true,
},
},
emits: ['setPostId'],
setup() {
const { isPending, isError, isFetching, data, error, refetch } = useQuery({
queryKey: ['posts'],
queryFn: fetcher,
})
return { isPending, isError, isFetching, data, error, refetch }
},
})
</script>
<template>
<h1>Posts</h1>
<div v-if="isPending">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<ul>
<li v-for="item in data" :key="item.id">
<a
@click="$emit('setPostId', item.id)"
href="#"
:class="{ visited: isVisited(item.id) }"
>{{ item.title }}</a
>
</li>
</ul>
</div>
</template>
<style scoped>
.visited {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,6 @@
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'
createApp(App).use(VueQueryPlugin).mount('#app')

5
examples/vue/basic/src/shims-vue.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

6
examples/vue/basic/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export interface Post {
userId: number
id: number
title: string
body: string
}

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}

View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
exclude: ['@tanstack/vue-query', 'vue-demi'],
},
})

View File

@@ -0,0 +1,6 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json

View File

@@ -0,0 +1,6 @@
# Dependent queries example
To run this example:
- `npm install` or `yarn`
- `npm run dev` or `yarn dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Query Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,19 @@
{
"name": "@tanstack/query-example-vue-dependent-queries",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@tanstack/vue-query": "^5.102.8",
"vue": "^3.4.27"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"typescript": "5.8.3",
"vite": "^6.4.1"
}
}

View File

@@ -0,0 +1,48 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Posts from './Posts.vue'
import Post from './Post.vue'
export default defineComponent({
name: 'App',
components: { Posts, Post },
setup() {
const visitedPosts = ref(new Set())
const isVisited = (id: number) => visitedPosts.value.has(id)
const postId = ref(-1)
const setPostId = (id: number) => {
visitedPosts.value.add(id)
postId.value = id
}
return {
isVisited,
postId,
setPostId,
}
},
})
</script>
<template>
<h1>Vue Query - Dependent Queries</h1>
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click
on any posts you have already visited again, you will see them load
instantly and background refresh right before your eyes!
<br />
You will also notice, that after some time the name of the author gets
loaded. This Data is not directly included in the
<code>/post/id</code> response but gets fetched when the post gets loaded
from its <code>userId</code>.
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
<Post v-if="postId > -1" :postId="postId" @setPostId="setPostId" />
<Posts v-else :isVisited="isVisited" @setPostId="setPostId" />
</template>

View File

@@ -0,0 +1,72 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Author, Post } from './types'
const fetchPost = async (id: number): Promise<Post> =>
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(
(response) => response.json(),
)
const fetchAuthor = async (id: number): Promise<Author> =>
await fetch(`https://jsonplaceholder.typicode.com/users/${id}`).then(
(response) => response.json(),
)
export default defineComponent({
name: 'PostDetails',
props: {
postId: {
type: Number,
required: true,
},
},
emits: ['setPostId'],
setup(props) {
const {
isPending,
isError,
isFetching,
data: post,
error,
} = useQuery({
queryKey: ['post', () => props.postId],
queryFn: () => fetchPost(props.postId),
})
const authorId = computed(() => post.value?.userId)
const { data: author } = useQuery({
queryKey: ['author', authorId],
queryFn: ({ queryKey: [, id] }) => fetchAuthor(id),
enabled: computed(() => !!authorId.value),
})
return { isPending, isError, isFetching, post, error, author }
},
})
</script>
<template>
<h1>Post {{ postId }}</h1>
<a @click="$emit('setPostId', -1)" href="#"> Back </a>
<div v-if="isPending" class="update">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="post">
<h1>
{{ post.title }} <span v-if="author">by {{ author.name }}</span>
</h1>
<div>
<p>{{ post.body }}</p>
</div>
<div v-if="isFetching" class="update">Background Updating...</div>
</div>
</template>
<style scoped>
.update {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,55 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Post } from './types'
const fetcher = async (): Promise<Post[]> =>
await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>
response.json(),
)
export default defineComponent({
name: 'PostsList',
props: {
isVisited: {
type: Function,
required: true,
},
},
emits: ['setPostId'],
setup() {
const { isPending, isError, isFetching, data, error, refetch } = useQuery({
queryKey: ['posts'],
queryFn: fetcher,
})
return { isPending, isError, isFetching, data, error, refetch }
},
})
</script>
<template>
<h1>Posts</h1>
<div v-if="isPending">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<ul>
<li v-for="item in data" :key="item.id">
<a
@click="$emit('setPostId', item.id)"
href="#"
:class="{ visited: isVisited(item.id) }"
>{{ item.title }}</a
>
</li>
</ul>
</div>
</template>
<style scoped>
.visited {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,6 @@
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'
createApp(App).use(VueQueryPlugin).mount('#app')

View File

@@ -0,0 +1,5 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

View File

@@ -0,0 +1,30 @@
export interface Post {
userId: number
id: number
title: string
body: string
}
export interface Author {
id: number
name: string
username: string
email: string
address: {
street: string
suite: string
city: string
zipcode: string
geo: {
lat: string
lng: string
}
}
phone: string
website: string
company: {
name: string
catchPhrase: string
bs: string
}
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
exclude: ['@tanstack/vue-query', 'vue-demi'],
},
})

10
examples/vue/nuxt3/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
node_modules
*.log
.nuxt
nuxt.d.ts
.output
.env
package-lock.json
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,29 @@
# Nuxt 3 Minimal Starter
We recommend looking at the [documentation](https://nuxt.com/docs/3.x/getting-started/introduction).
## Setup
Make sure to install the dependencies
```bash
pnpm install
```
## Development
Start the development server on http://localhost:3000
```bash
pnpm dev
```
## Production
Build the application for production:
```bash
pnpm build
```
Check out the [deployment documentation](https://nuxt.com/docs/3.x/getting-started/deployment).

View File

@@ -0,0 +1,16 @@
<template>
<div>{{ data }}</div>
</template>
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
const fetcher = async () =>
await fetch('https://jsonplaceholder.typicode.com/posts').then((response) =>
response.json(),
)
const { data, suspense } = useQuery({ queryKey: ['test'], queryFn: fetcher })
await suspense()
</script>

View File

@@ -0,0 +1,4 @@
import { defineNuxtConfig } from 'nuxt/config'
// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config
export default defineNuxtConfig({})

View File

@@ -0,0 +1,15 @@
{
"name": "@tanstack/query-example-vue-nuxt3",
"private": true,
"scripts": {
"dev": "nuxi dev",
"_build": "nuxi build",
"_start": "node .output/server/index.mjs"
},
"dependencies": {
"@tanstack/vue-query": "^5.90.2"
},
"devDependencies": {
"nuxt": "^3.12.4"
}
}

View File

@@ -0,0 +1,36 @@
import type {
DehydratedState,
VueQueryPluginOptions,
} from '@tanstack/vue-query'
import {
VueQueryPlugin,
QueryClient,
hydrate,
dehydrate,
} from '@tanstack/vue-query'
// Nuxt 3 app aliases
import { defineNuxtPlugin, useState } from '#imports'
export default defineNuxtPlugin((nuxt) => {
const vueQueryState = useState<DehydratedState | null>('vue-query')
// Modify your Vue Query global settings here
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 5000 } },
})
const options: VueQueryPluginOptions = { queryClient }
nuxt.vueApp.use(VueQueryPlugin, options)
if (import.meta.server) {
nuxt.hooks.hook('app:rendered', () => {
vueQueryState.value = dehydrate(queryClient)
})
}
if (import.meta.client && vueQueryState.value !== null) {
nuxt.hooks.hook('app:created', () => {
hydrate(queryClient, vueQueryState.value)
})
}
})

View File

@@ -0,0 +1,4 @@
{
// https://v3.nuxtjs.org/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}

6
examples/vue/persister/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json

View File

@@ -0,0 +1,6 @@
# Persister example
To run this example:
- `npm install` or `yarn`
- `npm run dev` or `yarn dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Query Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,23 @@
{
"name": "@tanstack/query-example-vue-persister",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@tanstack/query-core": "^5.102.8",
"@tanstack/query-persist-client-core": "^5.102.8",
"@tanstack/query-sync-storage-persister": "^5.102.8",
"@tanstack/vue-query": "^5.102.8",
"idb-keyval": "^6.2.1",
"vue": "^3.4.27"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"typescript": "5.8.3",
"vite": "^6.4.1"
}
}

View File

@@ -0,0 +1,43 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Posts from './Posts.vue'
import Post from './Post.vue'
export default defineComponent({
name: 'App',
components: { Posts, Post },
setup() {
const visitedPosts = ref(new Set())
const isVisited = (id: number) => visitedPosts.value.has(id)
const postId = ref(-1)
const setPostId = (id: number) => {
visitedPosts.value.add(id)
postId.value = id
}
return {
isVisited,
postId,
setPostId,
}
},
})
</script>
<template>
<h1>Vue Query - Basic</h1>
<p>
As you visit the posts below, you will notice them in a loading state the
first time you load them. However, after you return to this list and click
on any posts you have already visited again, you will see them load
instantly and background refresh right before your eyes!
<strong>
(You may need to throttle your network speed to simulate longer loading
sequences)
</strong>
</p>
<Post v-if="postId > -1" :postId="postId" @setPostId="setPostId" />
<Posts v-else :isVisited="isVisited" @setPostId="setPostId" />
</template>

View File

@@ -0,0 +1,61 @@
<script lang="ts">
import { get, set, del, entries } from 'idb-keyval'
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Post } from './types'
import { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'
const fetcher = async (id: number): Promise<Post> =>
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`).then(
(response) => response.json(),
)
export default defineComponent({
name: 'PostDetails',
props: {
postId: {
type: Number,
required: true,
},
},
emits: ['setPostId'],
setup(props) {
const { isPending, isError, isFetching, data, error } = useQuery({
queryKey: ['post', () => props.postId] as const,
queryFn: () => fetcher(props.postId),
persister: experimental_createQueryPersister({
storage: {
getItem: (key: string) => get(key),
setItem: (key: string, value: string) => set(key, value),
removeItem: (key: string) => del(key),
entries: () => entries<string>(),
},
}).persisterFn,
})
return { isPending, isError, isFetching, data, error }
},
})
</script>
<template>
<h1>Post {{ postId }}</h1>
<a @click="$emit('setPostId', -1)" href="#"> Back </a>
<div v-if="isPending" class="update">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<h1>{{ data.title }}</h1>
<div>
<p>{{ data.body }}</p>
</div>
<div v-if="isFetching" class="update">Background Updating...</div>
</div>
</template>
<style scoped>
.update {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,80 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { experimental_createQueryPersister } from '@tanstack/query-persist-client-core'
import { Post } from './types'
const fetcher = async (): Promise<Post[]> =>
await fetch('https://jsonplaceholder.typicode.com/posts').then(
(response) =>
new Promise((resolve) =>
setTimeout(() => resolve(response.json()), 1000),
),
)
export default defineComponent({
name: 'PostsList',
props: {
isVisited: {
type: Function,
required: true,
},
},
emits: ['setPostId'],
setup() {
const {
isPending,
isError,
isFetching,
isRefetching,
data,
error,
refetch,
} = useQuery({
queryKey: ['posts'] as const,
queryFn: () => fetcher(),
persister: experimental_createQueryPersister({
storage: localStorage,
}).persisterFn,
staleTime: 5000,
})
return {
isPending,
isRefetching,
isError,
isFetching,
data,
error,
refetch,
}
},
})
</script>
<template>
<h1>Posts</h1>
<div v-if="isRefetching">Refetching...</div>
<div v-if="isPending">Loading...</div>
<div v-else-if="isError">An error has occurred: {{ error }}</div>
<div v-else-if="data">
<ul>
<li v-for="item in data" :key="item.id">
<a
@click="$emit('setPostId', item.id)"
href="#"
:class="{ visited: isVisited(item.id) }"
>{{ item.title }}</a
>
</li>
</ul>
</div>
</template>
<style scoped>
.visited {
font-weight: bold;
color: green;
}
</style>

View File

@@ -0,0 +1,18 @@
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import type { VueQueryPluginOptions } from '@tanstack/vue-query'
import App from './App.vue'
const vueQueryOptions: VueQueryPluginOptions = {
queryClientConfig: {
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24,
// staleTime: 1000 * 10,
},
},
},
}
createApp(App).use(VueQueryPlugin, vueQueryOptions).mount('#app')

View File

@@ -0,0 +1,5 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

6
examples/vue/persister/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export interface Post {
userId: number
id: number
title: string
body: string
}

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}

View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
exclude: ['@tanstack/vue-query', 'vue-demi'],
},
})

9
examples/vue/simple/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
package-lock.json
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,6 @@
# Simple example
To run this example:
- `npm install` or `yarn` or `pnpm i` or `bun i`
- `npm run dev` or `yarn dev` or `pnpm dev` or `bun dev`

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TanStack Query Vue Simple Example App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,20 @@
{
"name": "@tanstack/query-example-vue-simple",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@tanstack/vue-query": "^5.102.8",
"@tanstack/vue-query-devtools": "^6.1.48",
"vue": "^3.4.27"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"typescript": "5.8.3",
"vite": "^6.4.1"
}
}

View File

@@ -0,0 +1,43 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { VueQueryDevtools } from '@tanstack/vue-query-devtools'
export default defineComponent({
name: 'App',
components: { VueQueryDevtools },
setup() {
const { data, error, isFetching, isPending } = useQuery({
queryKey: ['repoData'],
async queryFn() {
return await fetch('https://api.github.com/repos/Tanstack/query').then(
(response) => response.json(),
)
},
})
return {
data,
error,
isFetching,
isPending,
}
},
})
</script>
<template>
<template v-if="isPending"> Loading... </template>
<template v-else-if="error">
'An error has occurred: {{ error.message }}
</template>
<template v-else>
<h1>{{ data.name }}</h1>
<p>{{ data.description }}</p>
<strong>👀 {{ data.subscribers_count }}</strong>
<strong>✨ {{ data.stargazers_count }}</strong>
<strong>🍴 {{ data.forks_count }}</strong>
<div>{{ isFetching ? 'Updating...' : '' }}</div>
</template>
<VueQueryDevtools />
</template>

View File

@@ -0,0 +1,6 @@
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'
createApp(App).use(VueQueryPlugin).mount('#app')

View File

@@ -0,0 +1,5 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

6
examples/vue/simple/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export interface Post {
userId: number
id: number
title: string
body: string
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}

View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
exclude: ['@tanstack/vue-query', 'vue-demi'],
},
})