feat(useLazyQuery): load returns Promise, fix #1486

This commit is contained in:
Guillaume Chau
2023-09-12 16:52:13 +02:00
parent daffd75db2
commit 96cc4fe78a
8 changed files with 200 additions and 30 deletions
+11 -2
View File
@@ -4,14 +4,23 @@ Extends [useQuery](./use-query.md)
## Additional Return
- `load(document?, variables?, options?)`: function to start querying. Returns `true` if it is the first time the query is called, `false` otherwise.
- `load(document?, variables?, options?)`: function to start querying. Returns `Promise<Result>` if it is the first time the query is called, `false` otherwise.
Example:
```js
const { load, refetch } = useLazyQuery(query, variables, options)
function fetchMyData () {
function fetchOrRefetch () {
load() || refetch()
}
function waitForLoad () {
try {
const result = await load()
// do something with result
} catch (error) {
// handle error
}
}
```
+22 -1
View File
@@ -825,9 +825,30 @@ export default {
</template>
```
### Getting the result
`load()` returns a Promise to the result of the first request if it's the first time the query is activated.
```js
const { result, load, refetch } = useLazyQuery(gql`
query list {
list
}
`)
// ...
async function myLoad () {
try {
const result = await load()
} catch (e) {
// Handle error
}
}
```
### Refetch lazy query
`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`.
`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`.
```js
const { result, load, refetch } = useLazyQuery(gql`
@@ -0,0 +1,40 @@
<script lang="ts" setup>
import gql from 'graphql-tag'
import { useLazyQuery } from '@vue/apollo-composable'
import { ref } from 'vue'
const { load } = useLazyQuery<{ list: string[] }>(gql`
query list {
list
}
`)
const result = ref<any>(null)
async function myLoad () {
const r = await load()
if (r) {
result.value = r.list
}
}
</script>
<template>
<div class="m-6">
<div>
<button
class="bg-green-200 rounded-lg p-4"
@click="myLoad()"
>
Load list
</button>
</div>
<div
v-if="result"
class="result"
>
Loaded {{ result.length }}
</div>
</div>
</template>
@@ -0,0 +1,54 @@
<script lang="ts" setup>
import gql from 'graphql-tag'
import { useLazyQuery } from '@vue/apollo-composable'
import { ref } from 'vue'
const { load } = useLazyQuery<{ list: string[] }>(gql`
query list {
list {
id
}
}
`)
const result = ref<any>(null)
const error = ref<any>(null)
async function myLoad () {
try {
const r = await load()
if (r) {
result.value = r.list
}
} catch (e) {
error.value = e
}
}
</script>
<template>
<div class="m-6">
<div>
<button
class="bg-green-200 rounded-lg p-4"
@click="myLoad()"
>
Load list
</button>
</div>
<div
v-if="result"
class="result"
>
Loaded {{ result.length }}
</div>
<div
v-if="error"
class="error"
>
Error: {{ error.message }}
</div>
</div>
</template>
@@ -30,6 +30,14 @@ export const router = createRouter({
path: '/lazy-query-immediately',
component: () => import('./components/LazyQueryImmediately.vue'),
},
{
path: '/lazy-query-load',
component: () => import('./components/LazyQueryLoad.vue'),
},
{
path: '/lazy-query-load-error',
component: () => import('./components/LazyQueryLoadError.vue'),
},
{
path: '/partial-error',
component: () => import('./components/PartialError.vue'),
@@ -0,0 +1,43 @@
describe('Vue 3 + Apollo Composable', () => {
beforeEach(() => {
cy.task('db:reset')
cy.visit('/')
})
it('useLazyQuery', () => {
cy.visit('/lazy-query')
cy.get('.list-disc').should('have.length', 0)
cy.get('button').click()
cy.get('.loading').should('be.visible')
cy.get('.loading').should('not.exist')
cy.get('.list-disc').should('have.length', 3)
cy.get('.list-disc').should('contain', 'a')
cy.get('.list-disc').should('contain', 'b')
cy.get('.list-disc').should('contain', 'c')
})
it('useLazyQuery refetch', () => {
cy.visit('/lazy-query')
cy.get('button').click()
cy.get('.list-disc').should('have.length', 3)
cy.get('[data-test-id="refetched"]').should('contain', 'false')
cy.get('button').click()
cy.get('.list-disc').should('have.length', 3)
cy.get('[data-test-id="refetched"]').should('contain', 'true')
})
it('useLazyQuery load result', () => {
cy.visit('/lazy-query-load')
cy.get('.result').should('not.exist')
cy.get('button').click()
cy.get('.result').should('contain', 'Loaded 3')
})
it('useLazyQuery load error', () => {
cy.visit('/lazy-query-load-error')
cy.get('.result').should('not.exist')
cy.get('button').click()
cy.get('.error').should('contain', 'Error')
cy.get('.result').should('not.exist')
})
})
@@ -84,30 +84,6 @@ describe('Vue 3 + Apollo Composable', () => {
cy.contains('.no-setup-query', 'Hello world!')
})
it('useLazyQuery', () => {
cy.visit('/lazy-query')
cy.get('.list-disc').should('have.length', 0)
cy.get('button').click()
cy.get('.loading').should('be.visible')
cy.get('.loading').should('not.exist')
cy.get('.list-disc').should('have.length', 3)
cy.get('.list-disc').should('contain', 'a')
cy.get('.list-disc').should('contain', 'b')
cy.get('.list-disc').should('contain', 'c')
})
it('useLazyQuery refetch', () => {
cy.visit('/lazy-query')
cy.get('button').click()
cy.get('.list-disc').should('have.length', 3)
cy.get('[data-test-id="refetched"]').should('contain', 'false')
cy.get('button').click()
cy.get('.loading').should('be.visible')
cy.get('.loading').should('not.exist')
cy.get('.list-disc').should('have.length', 3)
cy.get('[data-test-id="refetched"]').should('contain', 'true')
})
it('enabled', () => {
cy.visit('/disabled')
cy.get('[data-test-id="data"]').should('not.exist')
@@ -26,9 +26,28 @@ export function useLazyQuery<
if (options) {
Object.assign(isRef(query.options) ? query.options.value : query.options, options)
}
const oldForceDisabled = query.forceDisabled.value
query.forceDisabled.value = false
return oldForceDisabled
const isFirstRun = query.forceDisabled.value
if (isFirstRun) {
query.forceDisabled.value = false
return new Promise<TResult>((resolve, reject) => {
const { off: offResult } = query.onResult((result) => {
if (!result.loading) {
console.log('result', result)
resolve(result.data)
offResult()
offError()
}
})
const { off: offError } = query.onError((error) => {
reject(error)
offResult()
offError()
})
})
} else {
return false
}
}
return {