From 96cc4fe78a8a594d2ed970e16395c0235186be1b Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 12 Sep 2023 16:52:13 +0200 Subject: [PATCH] feat(useLazyQuery): load returns Promise, fix #1486 --- packages/docs/src/api/use-lazy-query.md | 13 ++++- packages/docs/src/guide-composable/query.md | 23 +++++++- .../src/components/LazyQueryLoad.vue | 40 ++++++++++++++ .../src/components/LazyQueryLoadError.vue | 54 +++++++++++++++++++ .../test-e2e-composable-vue3/src/router.ts | 8 +++ .../tests/e2e/specs/lazy.cy.ts | 43 +++++++++++++++ .../tests/e2e/specs/test.cy.ts | 24 --------- .../vue-apollo-composable/src/useLazyQuery.ts | 25 +++++++-- 8 files changed, 200 insertions(+), 30 deletions(-) create mode 100644 packages/test-e2e-composable-vue3/src/components/LazyQueryLoad.vue create mode 100644 packages/test-e2e-composable-vue3/src/components/LazyQueryLoadError.vue create mode 100644 packages/test-e2e-composable-vue3/tests/e2e/specs/lazy.cy.ts diff --git a/packages/docs/src/api/use-lazy-query.md b/packages/docs/src/api/use-lazy-query.md index d70b88c..103ff1b 100644 --- a/packages/docs/src/api/use-lazy-query.md +++ b/packages/docs/src/api/use-lazy-query.md @@ -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` 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 + } + } ``` diff --git a/packages/docs/src/guide-composable/query.md b/packages/docs/src/guide-composable/query.md index 56c95b2..dcc59c0 100644 --- a/packages/docs/src/guide-composable/query.md +++ b/packages/docs/src/guide-composable/query.md @@ -825,9 +825,30 @@ export default { ``` +### 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` diff --git a/packages/test-e2e-composable-vue3/src/components/LazyQueryLoad.vue b/packages/test-e2e-composable-vue3/src/components/LazyQueryLoad.vue new file mode 100644 index 0000000..9fc68ce --- /dev/null +++ b/packages/test-e2e-composable-vue3/src/components/LazyQueryLoad.vue @@ -0,0 +1,40 @@ + + + diff --git a/packages/test-e2e-composable-vue3/src/components/LazyQueryLoadError.vue b/packages/test-e2e-composable-vue3/src/components/LazyQueryLoadError.vue new file mode 100644 index 0000000..45ca48d --- /dev/null +++ b/packages/test-e2e-composable-vue3/src/components/LazyQueryLoadError.vue @@ -0,0 +1,54 @@ + + + diff --git a/packages/test-e2e-composable-vue3/src/router.ts b/packages/test-e2e-composable-vue3/src/router.ts index 6fd05f5..51bbbdc 100644 --- a/packages/test-e2e-composable-vue3/src/router.ts +++ b/packages/test-e2e-composable-vue3/src/router.ts @@ -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'), diff --git a/packages/test-e2e-composable-vue3/tests/e2e/specs/lazy.cy.ts b/packages/test-e2e-composable-vue3/tests/e2e/specs/lazy.cy.ts new file mode 100644 index 0000000..d7b362e --- /dev/null +++ b/packages/test-e2e-composable-vue3/tests/e2e/specs/lazy.cy.ts @@ -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') + }) +}) diff --git a/packages/test-e2e-composable-vue3/tests/e2e/specs/test.cy.ts b/packages/test-e2e-composable-vue3/tests/e2e/specs/test.cy.ts index 606ae7d..d2a37ce 100644 --- a/packages/test-e2e-composable-vue3/tests/e2e/specs/test.cy.ts +++ b/packages/test-e2e-composable-vue3/tests/e2e/specs/test.cy.ts @@ -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') diff --git a/packages/vue-apollo-composable/src/useLazyQuery.ts b/packages/vue-apollo-composable/src/useLazyQuery.ts index 6cfec9a..a0aed5f 100644 --- a/packages/vue-apollo-composable/src/useLazyQuery.ts +++ b/packages/vue-apollo-composable/src/useLazyQuery.ts @@ -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((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 {