Skip to content

Commit e794c1e

Browse files
committed
feat: keepPreviousResult
1 parent 13bfbbe commit e794c1e

File tree

6 files changed

+156
-2
lines changed

6 files changed

+156
-2
lines changed

packages/docs/src/api/use-query.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
- `throttle`: Throttle interval in ms.
4444

45+
- `keepPreviousResult`: (default: `false`) Whether or not to keep previous result when the query is fetch again (for example when a variable changes). This can be useful to prevent a flash of empty content.
46+
4547
## Return
4648

4749
- `result`: result data object.

packages/test-e2e-composable-vue3/src/components/ChannelView.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export default defineComponent({
3434
id: props.id,
3535
}), {
3636
notifyOnNetworkStatusChange: true,
37-
keepPreviousResult: true,
3837
})
3938
const channel = computed(() => result.value?.channel)
4039
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<script lang="ts" setup>
2+
import { useApolloClient, useQuery } from '@vue/apollo-composable'
3+
import gql from 'graphql-tag'
4+
import { computed, ref } from 'vue'
5+
import MessageItem from './MessageItem.vue'
6+
7+
interface Channel {
8+
id: string
9+
label: string
10+
}
11+
12+
const keepPreviousResult = ref(false)
13+
14+
const channelsQuery = useQuery<{ channels: Channel[] }>(gql`
15+
query channels {
16+
channels {
17+
id
18+
label
19+
}
20+
}
21+
`)
22+
23+
const channels = computed(() => channelsQuery.result.value?.channels ?? [])
24+
25+
const selectedChannelId = ref<string | null>(null)
26+
27+
const selectedChannelQuery = useQuery(gql`
28+
query channel ($id: ID!) {
29+
channel (id: $id) {
30+
id
31+
label
32+
messages {
33+
id
34+
text
35+
}
36+
}
37+
}
38+
`, () => ({
39+
id: selectedChannelId.value,
40+
}), () => ({
41+
enabled: !!selectedChannelId.value,
42+
fetchPolicy: 'cache-and-network',
43+
keepPreviousResult: keepPreviousResult.value,
44+
}))
45+
46+
const selectedChannel = computed(() => selectedChannelQuery.result.value?.channel)
47+
48+
const { client: apolloClient } = useApolloClient()
49+
50+
function clearCache () {
51+
apolloClient.clearStore()
52+
}
53+
</script>
54+
55+
<template>
56+
<div class="h-full flex flex-col">
57+
<div class="p-4">
58+
<label>
59+
<input
60+
v-model="keepPreviousResult"
61+
type="checkbox"
62+
>
63+
keepPreviousResult
64+
</label>
65+
66+
<button
67+
class="ml-4 underline"
68+
@click="clearCache"
69+
>
70+
Clear cache
71+
</button>
72+
</div>
73+
74+
<div class="flex h-full">
75+
<div class="flex flex-col">
76+
<button
77+
v-for="channel of channels"
78+
:key="channel.id"
79+
class="channel-btn p-4"
80+
:class="{
81+
'bg-green-200': selectedChannelId === channel.id,
82+
}"
83+
@click="selectedChannelId = channel.id"
84+
>
85+
{{ channel.label }}
86+
</button>
87+
</div>
88+
89+
<div
90+
v-if="selectedChannel"
91+
class="the-channel flex flex-col w-full h-full overflow-auto"
92+
>
93+
<div class="flex-none p-6 border-b border-gray-200 bg-white">
94+
# {{ selectedChannel.label }}
95+
</div>
96+
97+
<div class="flex-1 overflow-y-auto">
98+
<MessageItem
99+
v-for="message of selectedChannel.messages"
100+
:key="message.id"
101+
:message="message"
102+
class="m-2"
103+
/>
104+
</div>
105+
</div>
106+
107+
<div
108+
v-else
109+
class="no-data"
110+
>
111+
No data
112+
</div>
113+
</div>
114+
</div>
115+
</template>

packages/test-e2e-composable-vue3/src/router.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,9 @@ export const router = createRouter({
4242
path: '/on-result',
4343
component: () => import('./components/OnResult.vue'),
4444
},
45+
{
46+
path: '/keep-previous-result',
47+
component: () => import('./components/KeepPreviousResult.vue'),
48+
},
4549
],
4650
})
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference types="Cypress" />
2+
3+
describe('keepPreviousResult', () => {
4+
beforeEach(() => {
5+
cy.task('db:reset')
6+
cy.visit('/keep-previous-result')
7+
})
8+
9+
it('keepPreviousResult disabled: should clear previous data', () => {
10+
cy.get('.no-data').should('be.visible')
11+
cy.get('.channel-btn').eq(0).click()
12+
cy.get('.no-data').should('be.visible')
13+
cy.get('.the-channel').should('contain.text', '# General')
14+
cy.get('.no-data').should('not.exist')
15+
cy.get('.channel-btn').eq(1).click()
16+
cy.get('.no-data').should('be.visible')
17+
cy.get('.the-channel').should('contain.text', '# Random')
18+
cy.get('.no-data').should('not.exist')
19+
})
20+
21+
it('keepPreviousResult enabled: should display previous channel', () => {
22+
cy.get('label').contains('keepPreviousResult').get('input[type="checkbox"]').check()
23+
cy.get('.no-data').should('be.visible')
24+
cy.get('.channel-btn').eq(0).click()
25+
cy.get('.no-data').should('be.visible')
26+
cy.get('.the-channel').should('contain.text', '# General')
27+
cy.get('.no-data').should('not.exist')
28+
cy.get('.channel-btn').eq(1).click()
29+
cy.get('.no-data').should('not.exist')
30+
cy.get('.the-channel').should('contain.text', '# General')
31+
cy.get('.the-channel').should('contain.text', '# Random')
32+
})
33+
})

packages/vue-apollo-composable/src/useQuery.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export interface UseQueryOptions<
4444
throttle?: number
4545
debounce?: number
4646
prefetch?: boolean
47+
keepPreviousResult?: boolean
4748
}
4849

4950
interface SubscribeToMoreItem {
@@ -256,7 +257,7 @@ export function useQueryImpl<
256257

257258
// Make the cache data available to the component immediately
258259
// This prevents SSR hydration mismatches
259-
if (!isServer && (currentOptions.value?.fetchPolicy !== 'no-cache' || currentOptions.value.notifyOnNetworkStatusChange)) {
260+
if (!isServer && !currentOptions.value?.keepPreviousResult && (currentOptions.value?.fetchPolicy !== 'no-cache' || currentOptions.value.notifyOnNetworkStatusChange)) {
260261
const currentResult = query.value.getCurrentResult(false)
261262

262263
if (!currentResult.loading || currentResult.partial || currentOptions.value?.notifyOnNetworkStatusChange) {

0 commit comments

Comments
 (0)