Skip to content

Commit e1eff52

Browse files
authoredNov 29, 2023
fix(query): enabled reactivity fix (new) (#1080)
* fix: move 943 changes into new master * fix: address https://github.com/anymaniax/orval/pull/944/files#r1347320242 * feat: tests * fix: oops
1 parent 1335879 commit e1eff52

10 files changed

+152
-16
lines changed
 

‎.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"cSpell.words": ["listitem", "Petstore", "tanstack"]
3+
}

‎packages/query/src/index.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,10 @@ const VUE_QUERY_DEPENDENCIES_V3: GeneratorDependency[] = [
231231
dependency: 'vue-query/types',
232232
},
233233
{
234-
exports: [{ name: 'unref', values: true }],
234+
exports: [
235+
{ name: 'unref', values: true },
236+
{ name: 'computed', values: true },
237+
],
235238
dependency: 'vue',
236239
},
237240
{
@@ -258,7 +261,10 @@ const VUE_QUERY_DEPENDENCIES: GeneratorDependency[] = [
258261
dependency: '@tanstack/vue-query',
259262
},
260263
{
261-
exports: [{ name: 'unref', values: true }],
264+
exports: [
265+
{ name: 'unref', values: true },
266+
{ name: 'computed', values: true },
267+
],
262268
dependency: 'vue',
263269
},
264270
{
@@ -506,10 +512,12 @@ const generateQueryOptions = ({
506512
params,
507513
options,
508514
type,
515+
outputClient,
509516
}: {
510517
params: GetterParams;
511518
options?: object | boolean;
512519
type: QueryType;
520+
outputClient: OutputClient | OutputClientFunc;
513521
}) => {
514522
if (options === false) {
515523
return '';
@@ -537,7 +545,11 @@ const generateQueryOptions = ({
537545

538546
return `${
539547
!isObject(options) || !options.hasOwnProperty('enabled')
540-
? `enabled: !!(${params.map(({ name }) => name).join(' && ')}),`
548+
? isVue(outputClient)
549+
? `enabled: computed(() => !!(${params
550+
.map(({ name }) => `unref(${name})`)
551+
.join(' && ')})),`
552+
: `enabled: !!(${params.map(({ name }) => name).join(' && ')}),`
541553
: ''
542554
}${queryConfig} ...queryOptions`;
543555
};
@@ -931,6 +943,7 @@ const generateQueryImplementation = ({
931943
params,
932944
options,
933945
type,
946+
outputClient,
934947
});
935948

936949
const queryOptionsFnName = camel(

‎samples/vue-query/src/api/endpoints/petstoreFromFileSpecWithTransformer.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type {
1616
UseQueryReturnType,
1717
} from '@tanstack/vue-query';
1818
import type { MaybeRef } from '@tanstack/vue-query/build/lib/types';
19-
import { unref } from 'vue';
19+
import { computed, unref } from 'vue';
2020
import type {
2121
CreatePetsBody,
2222
Error,
@@ -83,7 +83,7 @@ export const getListPetsInfiniteQueryOptions = <
8383
return {
8484
queryKey,
8585
queryFn,
86-
enabled: !!version,
86+
enabled: computed(() => !!unref(version)),
8787
...queryOptions,
8888
} as UseInfiniteQueryOptions<
8989
Awaited<ReturnType<typeof listPets>>,
@@ -155,7 +155,7 @@ export const getListPetsQueryOptions = <
155155
return {
156156
queryKey,
157157
queryFn,
158-
enabled: !!version,
158+
enabled: computed(() => !!unref(version)),
159159
...queryOptions,
160160
} as UseQueryOptions<Awaited<ReturnType<typeof listPets>>, TError, TData>;
161161
};
@@ -313,7 +313,7 @@ export const getShowPetByIdInfiniteQueryOptions = <
313313
return {
314314
queryKey,
315315
queryFn,
316-
enabled: !!(version && petId),
316+
enabled: computed(() => !!(unref(version) && unref(petId))),
317317
...queryOptions,
318318
} as UseInfiniteQueryOptions<
319319
Awaited<ReturnType<typeof showPetById>>,
@@ -385,7 +385,7 @@ export const getShowPetByIdQueryOptions = <
385385
return {
386386
queryKey,
387387
queryFn,
388-
enabled: !!(version && petId),
388+
enabled: computed(() => !!(unref(version) && unref(petId))),
389389
...queryOptions,
390390
} as UseQueryOptions<Awaited<ReturnType<typeof showPetById>>, TError, TData>;
391391
};

‎samples/vue-query/src/components/pet.vue

+2-6
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77
</template>
88

99
<script lang="ts" setup>
10-
import { computed, ref, unref } from 'vue';
10+
import { computed, unref } from 'vue';
1111
import { useShowPetById } from '../api/endpoints/petstoreFromFileSpecWithTransformer';
1212
1313
const props = defineProps<{ petId: string }>();
14-
const overridePetId = ref<string | undefined>();
15-
setTimeout(() => {
16-
overridePetId.value = '123';
17-
}, 100);
18-
const petId = computed(() => overridePetId.value || props.petId);
14+
const petId = computed(() => props.petId);
1915
const petQuery = useShowPetById(petId);
2016
const pet = computed(() => unref(petQuery?.data));
2117
</script>

‎samples/vue-query/src/components/pet.spec.ts ‎samples/vue-query/src/components/tests/path-parameter-reactivity-pet.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { VueQueryPlugin } from '@tanstack/vue-query';
22
import { render, screen, waitFor } from '@testing-library/vue';
33
import { http } from 'msw';
44
import { describe, expect, it } from 'vitest';
5-
import { server } from '../mocks/server';
6-
import Pet from './pet.vue';
5+
import { server } from '../../mocks/server';
6+
import Pet from './path-parameter-reactivity-pet.vue';
77

88
describe('Path parameters reactivity', () => {
99
it('works', async () => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<div v-if="pet && petId" :key="pet.id">
3+
{{ petId }}
4+
{{ pet }}
5+
<span>{{ pet.name }}</span>
6+
</div>
7+
</template>
8+
9+
<script lang="ts" setup>
10+
import { computed, ref, unref } from 'vue';
11+
import { useShowPetById } from '../../api/endpoints/petstoreFromFileSpecWithTransformer';
12+
13+
const props = defineProps<{ petId: string }>();
14+
const overridePetId = ref<string | undefined>();
15+
setTimeout(() => {
16+
overridePetId.value = '123';
17+
}, 100);
18+
const petId = computed(() => overridePetId.value || props.petId);
19+
const petQuery = useShowPetById(petId);
20+
const pet = computed(() => unref(petQuery?.data));
21+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { VueQueryPlugin } from '@tanstack/vue-query';
2+
import { render, waitFor } from '@testing-library/vue';
3+
import { describe, expect, it, vi } from 'vitest';
4+
import * as customInstanceModule from '../../api/mutator/custom-instance';
5+
import Pet from './query-enabled-reactivity-pet-id.vue';
6+
7+
describe('Query `enabled` reactivity', () => {
8+
it('works', async () => {
9+
// this test is to ensure that we use unref() for `enabled`, like so: `enabled: computed(() => !!unref(petId))`
10+
11+
const spy = vi.spyOn(customInstanceModule, 'customInstance');
12+
13+
render(Pet, {
14+
global: {
15+
plugins: [VueQueryPlugin],
16+
},
17+
});
18+
19+
// make sure the query is disabled at first, because `petId` is falsy (empty string)
20+
expect(spy).not.toHaveBeenCalled();
21+
22+
// after the timeout inside of component, `overridePetId` is set to `123` and the query is enabled
23+
await waitFor(() => {
24+
expect(spy).toHaveBeenCalledWith(
25+
expect.objectContaining({
26+
url: '/v1/pets/123',
27+
}),
28+
);
29+
});
30+
});
31+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<div v-if="pet && petId" :key="pet.id">
3+
{{ petId }}
4+
{{ pet }}
5+
<span>{{ pet.name }}</span>
6+
</div>
7+
</template>
8+
9+
<script lang="ts" setup>
10+
import { computed, ref, unref } from 'vue';
11+
import { useShowPetById } from '../../api/endpoints/petstoreFromFileSpecWithTransformer';
12+
13+
const overridePetId = ref<string | undefined>();
14+
setTimeout(() => {
15+
overridePetId.value = '123';
16+
}, 100);
17+
const petId = computed(() => overridePetId.value ?? '');
18+
const petQuery = useShowPetById(petId);
19+
const pet = computed(() => unref(petQuery?.data));
20+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { VueQueryPlugin } from '@tanstack/vue-query';
2+
import { render, waitFor } from '@testing-library/vue';
3+
import { describe, expect, it, vi } from 'vitest';
4+
import * as customInstanceModule from '../../api/mutator/custom-instance';
5+
import Pet from './query-enabled-reactivity-version.vue';
6+
7+
describe('Query `enabled` reactivity', () => {
8+
it('works for multiple arguments (version and petId)', async () => {
9+
// this test is to ensure we don't use `unref(version && petId)` which is not correct, see https://github.com/anymaniax/orval/pull/944/files#r1347320242
10+
11+
const spy = vi.spyOn(customInstanceModule, 'customInstance');
12+
13+
render(Pet, {
14+
global: {
15+
plugins: [VueQueryPlugin],
16+
},
17+
});
18+
19+
// make sure the query is disabled at first, because `petId` is falsy (empty string)
20+
expect(spy).not.toHaveBeenCalled();
21+
22+
// after the timeout inside of component, `overridePetId` is set to `123` and the query is enabled
23+
await waitFor(() => {
24+
expect(spy).toHaveBeenCalledWith(
25+
expect.objectContaining({
26+
url: '/v1/pets/123',
27+
}),
28+
);
29+
});
30+
});
31+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<div v-if="pet && petId" :key="pet.id">
3+
{{ petId }}
4+
{{ pet }}
5+
<span>{{ pet.name }}</span>
6+
</div>
7+
</template>
8+
9+
<script lang="ts" setup>
10+
import { computed, ref, unref } from 'vue';
11+
import { useShowPetById } from '../../api/endpoints/petstoreFromFileSpecWithTransformer';
12+
13+
setTimeout(() => {
14+
version.value = 1;
15+
}, 100);
16+
const petId = ref('123');
17+
const version = ref(0);
18+
// @ts-expect-error // version has `number` type instead of `MaybeRef<number>` because of its default value of 1, still version is being trated like ref, so it works. This probably should be addressed separately
19+
const petQuery = useShowPetById(petId, version);
20+
const pet = computed(() => unref(petQuery?.data));
21+
</script>

0 commit comments

Comments
 (0)
Please sign in to comment.