Skip to content

Commit 96cc4fe

Browse files
committed
feat(useLazyQuery): load returns Promise, fix #1486
1 parent daffd75 commit 96cc4fe

File tree

8 files changed

+200
-30
lines changed

8 files changed

+200
-30
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,23 @@ Extends [useQuery](./use-query.md)
44

55
## Additional Return
66

7-
- `load(document?, variables?, options?)`: function to start querying. Returns `true` if it is the first time the query is called, `false` otherwise.
7+
- `load(document?, variables?, options?)`: function to start querying. Returns `Promise<Result>` if it is the first time the query is called, `false` otherwise.
88

99
Example:
1010

1111
```js
1212
const { load, refetch } = useLazyQuery(query, variables, options)
1313

14-
function fetchMyData () {
14+
function fetchOrRefetch () {
1515
load() || refetch()
1616
}
17+
18+
function waitForLoad () {
19+
try {
20+
const result = await load()
21+
// do something with result
22+
} catch (error) {
23+
// handle error
24+
}
25+
}
1726
```

packages/docs/src/guide-composable/query.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,9 +825,30 @@ export default {
825825
</template>
826826
```
827827

828+
### Getting the result
829+
830+
`load()` returns a Promise to the result of the first request if it's the first time the query is activated.
831+
832+
```js
833+
const { result, load, refetch } = useLazyQuery(gql`
834+
query list {
835+
list
836+
}
837+
`)
838+
// ...
839+
840+
async function myLoad () {
841+
try {
842+
const result = await load()
843+
} catch (e) {
844+
// Handle error
845+
}
846+
}
847+
```
848+
828849
### Refetch lazy query
829850

830-
`load()` returns `true` if it is the first time the query is activated, `false` otherwise. You can use this to refetch the query with `refetch()` in case the user clicks on the button again, meaning `load()` returns `false`.
851+
`load()` returns `false` if it is not the first time the query is activated. You can use this to refetch the query with `refetch()` in case the user clicks on the button again, meaning `load()` returns `false`.
831852

832853
```js
833854
const { result, load, refetch } = useLazyQuery(gql`
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<script lang="ts" setup>
2+
import gql from 'graphql-tag'
3+
import { useLazyQuery } from '@vue/apollo-composable'
4+
import { ref } from 'vue'
5+
6+
const { load } = useLazyQuery<{ list: string[] }>(gql`
7+
query list {
8+
list
9+
}
10+
`)
11+
12+
const result = ref<any>(null)
13+
14+
async function myLoad () {
15+
const r = await load()
16+
if (r) {
17+
result.value = r.list
18+
}
19+
}
20+
</script>
21+
22+
<template>
23+
<div class="m-6">
24+
<div>
25+
<button
26+
class="bg-green-200 rounded-lg p-4"
27+
@click="myLoad()"
28+
>
29+
Load list
30+
</button>
31+
</div>
32+
33+
<div
34+
v-if="result"
35+
class="result"
36+
>
37+
Loaded {{ result.length }}
38+
</div>
39+
</div>
40+
</template>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script lang="ts" setup>
2+
import gql from 'graphql-tag'
3+
import { useLazyQuery } from '@vue/apollo-composable'
4+
import { ref } from 'vue'
5+
6+
const { load } = useLazyQuery<{ list: string[] }>(gql`
7+
query list {
8+
list {
9+
id
10+
}
11+
}
12+
`)
13+
14+
const result = ref<any>(null)
15+
const error = ref<any>(null)
16+
17+
async function myLoad () {
18+
try {
19+
const r = await load()
20+
if (r) {
21+
result.value = r.list
22+
}
23+
} catch (e) {
24+
error.value = e
25+
}
26+
}
27+
</script>
28+
29+
<template>
30+
<div class="m-6">
31+
<div>
32+
<button
33+
class="bg-green-200 rounded-lg p-4"
34+
@click="myLoad()"
35+
>
36+
Load list
37+
</button>
38+
</div>
39+
40+
<div
41+
v-if="result"
42+
class="result"
43+
>
44+
Loaded {{ result.length }}
45+
</div>
46+
47+
<div
48+
v-if="error"
49+
class="error"
50+
>
51+
Error: {{ error.message }}
52+
</div>
53+
</div>
54+
</template>

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ export const router = createRouter({
3030
path: '/lazy-query-immediately',
3131
component: () => import('./components/LazyQueryImmediately.vue'),
3232
},
33+
{
34+
path: '/lazy-query-load',
35+
component: () => import('./components/LazyQueryLoad.vue'),
36+
},
37+
{
38+
path: '/lazy-query-load-error',
39+
component: () => import('./components/LazyQueryLoadError.vue'),
40+
},
3341
{
3442
path: '/partial-error',
3543
component: () => import('./components/PartialError.vue'),
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
describe('Vue 3 + Apollo Composable', () => {
2+
beforeEach(() => {
3+
cy.task('db:reset')
4+
cy.visit('/')
5+
})
6+
7+
it('useLazyQuery', () => {
8+
cy.visit('/lazy-query')
9+
cy.get('.list-disc').should('have.length', 0)
10+
cy.get('button').click()
11+
cy.get('.loading').should('be.visible')
12+
cy.get('.loading').should('not.exist')
13+
cy.get('.list-disc').should('have.length', 3)
14+
cy.get('.list-disc').should('contain', 'a')
15+
cy.get('.list-disc').should('contain', 'b')
16+
cy.get('.list-disc').should('contain', 'c')
17+
})
18+
19+
it('useLazyQuery refetch', () => {
20+
cy.visit('/lazy-query')
21+
cy.get('button').click()
22+
cy.get('.list-disc').should('have.length', 3)
23+
cy.get('[data-test-id="refetched"]').should('contain', 'false')
24+
cy.get('button').click()
25+
cy.get('.list-disc').should('have.length', 3)
26+
cy.get('[data-test-id="refetched"]').should('contain', 'true')
27+
})
28+
29+
it('useLazyQuery load result', () => {
30+
cy.visit('/lazy-query-load')
31+
cy.get('.result').should('not.exist')
32+
cy.get('button').click()
33+
cy.get('.result').should('contain', 'Loaded 3')
34+
})
35+
36+
it('useLazyQuery load error', () => {
37+
cy.visit('/lazy-query-load-error')
38+
cy.get('.result').should('not.exist')
39+
cy.get('button').click()
40+
cy.get('.error').should('contain', 'Error')
41+
cy.get('.result').should('not.exist')
42+
})
43+
})

packages/test-e2e-composable-vue3/tests/e2e/specs/test.cy.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -84,30 +84,6 @@ describe('Vue 3 + Apollo Composable', () => {
8484
cy.contains('.no-setup-query', 'Hello world!')
8585
})
8686

87-
it('useLazyQuery', () => {
88-
cy.visit('/lazy-query')
89-
cy.get('.list-disc').should('have.length', 0)
90-
cy.get('button').click()
91-
cy.get('.loading').should('be.visible')
92-
cy.get('.loading').should('not.exist')
93-
cy.get('.list-disc').should('have.length', 3)
94-
cy.get('.list-disc').should('contain', 'a')
95-
cy.get('.list-disc').should('contain', 'b')
96-
cy.get('.list-disc').should('contain', 'c')
97-
})
98-
99-
it('useLazyQuery refetch', () => {
100-
cy.visit('/lazy-query')
101-
cy.get('button').click()
102-
cy.get('.list-disc').should('have.length', 3)
103-
cy.get('[data-test-id="refetched"]').should('contain', 'false')
104-
cy.get('button').click()
105-
cy.get('.loading').should('be.visible')
106-
cy.get('.loading').should('not.exist')
107-
cy.get('.list-disc').should('have.length', 3)
108-
cy.get('[data-test-id="refetched"]').should('contain', 'true')
109-
})
110-
11187
it('enabled', () => {
11288
cy.visit('/disabled')
11389
cy.get('[data-test-id="data"]').should('not.exist')

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,28 @@ export function useLazyQuery<
2626
if (options) {
2727
Object.assign(isRef(query.options) ? query.options.value : query.options, options)
2828
}
29-
const oldForceDisabled = query.forceDisabled.value
30-
query.forceDisabled.value = false
31-
return oldForceDisabled
29+
const isFirstRun = query.forceDisabled.value
30+
if (isFirstRun) {
31+
query.forceDisabled.value = false
32+
33+
return new Promise<TResult>((resolve, reject) => {
34+
const { off: offResult } = query.onResult((result) => {
35+
if (!result.loading) {
36+
console.log('result', result)
37+
resolve(result.data)
38+
offResult()
39+
offError()
40+
}
41+
})
42+
const { off: offError } = query.onError((error) => {
43+
reject(error)
44+
offResult()
45+
offError()
46+
})
47+
})
48+
} else {
49+
return false
50+
}
3251
}
3352

3453
return {

0 commit comments

Comments
 (0)