Skip to content

Commit a7e7b60

Browse files
committed
feat: add mutation functionality to playground
1 parent 93067b5 commit a7e7b60

File tree

3 files changed

+88
-48
lines changed

3 files changed

+88
-48
lines changed

client/app/pages/vue-query.vue

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,16 @@ const filteredQueries = computed(() => {
2121
2222
function onQueryNotification(event: QueryCacheNotifyEvent) {
2323
switch (event.type) {
24+
case 'observerResultsUpdated':
25+
// TODO: when data becomes stale/invalidate etc, the query is updated
26+
// fall through
2427
case 'updated': {
2528
const query = queries.value.find(q => q.queryHash === event.query.queryHash)
2629
if (query) {
2730
query.state = { ...event.query.state }
2831
}
2932
break
3033
}
31-
case 'observerResultsUpdated': {
32-
// TODO: when data becomes stale, the query is updated
33-
console.log('Query observerResultsUpdated', event.query.queryKey, event.query.isStale(), event.query.state)
34-
break
35-
}
3634
case 'added':
3735
queries.value.push(event.query)
3836
break

playground/app/app.vue

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup>
22
const selectedUser = ref(null)
3+
const queryClient = useQueryClient()
34
45
const getUsers = async () => {
56
await new Promise(resolve => setTimeout(resolve, 2000))
@@ -21,63 +22,104 @@ const selectedUserId = computed(() => selectedUser.value?.id)
2122
const { isPending, isFetching, isError, data: posts, error } = useQuery({
2223
queryKey: ['posts', selectedUserId],
2324
queryFn: () => getPosts(selectedUserId.value),
24-
staleTime: 1000 * 10, // for 10 seconds it fill be considered as "fresh"
25+
staleTime: 1000 * 10, // for 10 seconds it will be considered as "fresh"
2526
gcTime: 1000 * 20, // after 20 seconds it will be garbage collected
26-
enabled: !selectedUser.value,
27+
enabled: computed(() => selectedUser.value !== null),
2728
2829
})
30+
31+
const { mutate: addPost, isPending: isMutationPending } = useMutation({
32+
mutationFn: async (post) => {
33+
const url = 'https://jsonplaceholder.typicode.com/posts'
34+
return await $fetch(url, { method: 'POST', body: post })
35+
},
36+
onSuccess: () => {
37+
queryClient.invalidateQueries({ queryKey: ['posts', selectedUserId] })
38+
},
39+
})
40+
2941
function selectUser(user) {
3042
selectedUser.value = user
3143
}
44+
45+
function addNewPost() {
46+
addPost({
47+
title: 'New Post',
48+
body: 'This is a new post',
49+
userId: selectedUserId.value,
50+
})
51+
}
3252
</script>
3353
3454
<template>
35-
<div>
36-
<h1>Users</h1>
37-
<div v-if="isUsersPending">
38-
Loading...
39-
</div>
40-
<div
41-
v-else
42-
:style="{
43-
display: 'grid',
44-
gap: '0.5rem',
45-
paddingLeft: '0.5rem',
46-
}"
47-
>
55+
<div
56+
:style="{
57+
display: 'grid',
58+
gridTemplateColumns: 'auto auto',
59+
gap: '2rem',
60+
}"
61+
>
62+
<div>
63+
<h1>Users</h1>
64+
<div v-if="isUsersPending">
65+
Loading...
66+
</div>
4867
<div
49-
v-for="user in users"
50-
:key="user.id"
68+
v-else
5169
:style="{
52-
cursor: 'pointer',
53-
backgroundColor: selectedUserId === user.id ? 'blue' : 'white',
54-
color: selectedUserId === user.id ? 'white' : 'black',
55-
padding: '0.25rem',
70+
display: 'grid',
71+
gap: '0.5rem',
72+
paddingLeft: '0.5rem',
5673
}"
57-
@click="selectUser(user)"
5874
>
59-
{{ user.name }} ({{ user.email }})
75+
<div
76+
v-for="user in users"
77+
:key="user.id"
78+
:style="{
79+
cursor: 'pointer',
80+
backgroundColor: selectedUserId === user.id ? 'blue' : 'white',
81+
color: selectedUserId === user.id ? 'white' : 'black',
82+
paddingTop: '0.25rem',
83+
}"
84+
@click="selectUser(user)"
85+
>
86+
{{ user.name }} ({{ user.email }})
87+
</div>
6088
</div>
6189
</div>
62-
</div>
63-
<div>
64-
<h1>Posts</h1>
65-
<div v-if="isPending">
66-
Loading...
67-
</div>
68-
<div v-else-if="isFetching">
69-
Fetching...
70-
</div>
71-
<ul v-else-if="isError">
72-
<li>Error: {{ error.message }}</li>
73-
</ul>
74-
<ul v-else>
75-
<li
76-
v-for="post in posts"
77-
:key="post.id"
90+
<div>
91+
<div
92+
:style="{
93+
display: 'flex',
94+
justifyContent: 'space-between',
95+
alignItems: 'center',
96+
}"
7897
>
79-
{{ post.title }}
80-
</li>
81-
</ul>
98+
<h1>Posts</h1>
99+
<button @click="addNewPost">
100+
Add Post
101+
</button>
102+
</div>
103+
<div v-if="isPending">
104+
Select a user first...
105+
</div>
106+
<div v-if="isMutationPending">
107+
Adding post...
108+
</div>
109+
<div v-else-if="isFetching">
110+
Fetching...
111+
</div>
112+
<ul v-else-if="isError">
113+
<li>Error: {{ error.message }}</li>
114+
</ul>
115+
<ul v-else>
116+
<li
117+
v-for="post in posts"
118+
:key="post.id"
119+
>
120+
{{ post.title }}
121+
</li>
122+
</ul>
123+
</div>
82124
</div>
83125
</template>

playground/nuxt.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default defineNuxtConfig({
88
},
99
compatibilityDate: '2025-02-14',
1010
nuxtQuery: {
11-
autoImports: ['useQuery'],
11+
autoImports: ['useQuery', 'useMutation', 'useQueryClient'],
1212
queryClientOptions: {
1313
defaultOptions: {
1414
queries: {

0 commit comments

Comments
 (0)