Last active
February 26, 2024 18:20
-
-
Save wobsoriano/9a7de2d2aaf9448c2fb952d2746b6907 to your computer and use it in GitHub Desktop.
TanStack Query + Vue Options API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import { defineComponent, toRaw } from 'vue' | |
import { | |
QueryObserver, | |
type QueryKey, | |
type QueryObserverResult, | |
type QueryClient, | |
} from '@tanstack/query-core' | |
type Todo = { | |
userId: number | |
id: number | |
title: string | |
completed: boolean | |
} | |
export default defineComponent({ | |
inject: ['queryClient'], | |
data: () => ({ | |
todoId: 1, | |
result: {} as QueryObserverResult<Todo, unknown>, | |
observer: null as null | QueryObserver<Todo, unknown, Todo, Todo, QueryKey>, | |
unsubscribe: () => {} | |
}), | |
methods: { | |
async fetchTodo(id: number) { | |
const resp = await fetch('https://jsonplaceholder.typicode.com/todos/' + id) | |
const data = await resp.json() | |
return data | |
}, | |
}, | |
mounted() { | |
this.observer = new QueryObserver<Todo, unknown, Todo, Todo, QueryKey>(this.queryClient as QueryClient, { | |
queryKey: ['todo', 1], | |
queryFn: () => this.fetchTodo(1), | |
}) | |
this.unsubscribe = this.observer.subscribe((result) => { | |
Object.keys(result).forEach((key) => { | |
// @ts-expect-error: Incompatible types | |
this.result[key] = result[key] | |
}) | |
}) | |
}, | |
beforeUnmount() { | |
this.unsubscribe() | |
}, | |
watch: { | |
todoId(id) { | |
toRaw(this.observer)?.setOptions({ | |
queryKey: ['todo', id], | |
queryFn: () => this.fetchTodo(id), | |
}) | |
} | |
} | |
}) | |
</script> | |
<template> | |
<main> | |
<div v-if="result.isLoading">Loading...</div> | |
<div v-else>{{ JSON.stringify(result.data) }}</div> | |
<button @click="todoId++" :disabled="result.isLoading"> | |
{{ result.isLoading ? 'Fetching...' : 'Next todo' }} | |
</button> | |
</main> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createApp } from 'vue' | |
import App from './App.vue' | |
import { QueryClient } from '@tanstack/query-core' | |
const app = createApp(App) | |
const queryClient = new QueryClient() | |
app.provide('queryClient', queryClient) | |
app.mount('#app') |
@Tajcore Looks like a Proxy bug somewhere. You can add toRaw
to the observer
property and the error is gone.
watch: {
todoId(id) {
toRaw(this.observer)?.setOptions({
queryKey: ['todo', id],
queryFn: () => this.fetchTodo(id),
})
}
}
Oh word I'm actually writing this using a class based approach using vue-facing-decorator
that doesn't support the dynamic nature of updating the queryKey sadly. would you update the gist though just asking?
Thanks seeing it now!
Hey @wobsoriano, how would you handle mutations? with just query-core
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
getting
Uncaught (in promise) TypeError: Cannot read from private field
fromthis.observer.setOptions