Skip to content

Commit 068df71

Browse files
authored
feat(vue): refactor composable functions (#3619)
1 parent 9e674d3 commit 068df71

9 files changed

+663
-376
lines changed

.changeset/chatty-mice-join.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@urql/vue': minor
3+
---
4+
5+
Refactor composable functions with a focus on avoiding memory leaks and Vue best practices

packages/vue-urql/src/useClientHandle.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { DocumentNode } from 'graphql';
2-
import type { AnyVariables, Client, TypedDocumentNode } from '@urql/core';
1+
import type { AnyVariables, Client, DocumentInput } from '@urql/core';
32
import type { WatchStopHandle } from 'vue';
43
import { getCurrentInstance, onMounted, onBeforeUnmount } from 'vue';
54

@@ -75,7 +74,7 @@ export interface ClientHandle {
7574
* function or when chained in an `async setup()` function.
7675
*/
7776
useMutation<T = any, V extends AnyVariables = AnyVariables>(
78-
query: TypedDocumentNode<T, V> | DocumentNode | string
77+
query: DocumentInput<T, V>
7978
): UseMutationResponse<T, V>;
8079
}
8180

@@ -153,7 +152,7 @@ export function useClientHandle(): ClientHandle {
153152
},
154153

155154
useMutation<T = any, V extends AnyVariables = AnyVariables>(
156-
query: TypedDocumentNode<T, V> | DocumentNode | string
155+
query: DocumentInput<T, V>
157156
): UseMutationResponse<T, V> {
158157
return callUseMutation(query, client);
159158
},

packages/vue-urql/src/useMutation.test.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { OperationResult, OperationResultSource } from '@urql/core';
2-
import { reactive } from 'vue';
2+
import { readonly } from 'vue';
33
import { vi, expect, it, beforeEach, describe } from 'vitest';
44

55
vi.mock('./useClient.ts', async () => {
@@ -30,15 +30,13 @@ describe('useMutation', () => {
3030
() => subject.source as OperationResultSource<OperationResult>
3131
);
3232

33-
const mutation = reactive(
34-
useMutation(gql`
35-
mutation {
36-
test
37-
}
38-
`)
39-
);
33+
const mutation = useMutation(gql`
34+
mutation {
35+
test
36+
}
37+
`);
4038

41-
expect(mutation).toMatchObject({
39+
expect(readonly(mutation)).toMatchObject({
4240
data: undefined,
4341
stale: false,
4442
fetching: false,
@@ -50,18 +48,18 @@ describe('useMutation', () => {
5048

5149
const promise = mutation.executeMutation({ test: true });
5250

53-
expect(mutation.fetching).toBe(true);
54-
expect(mutation.stale).toBe(false);
55-
expect(mutation.error).toBe(undefined);
51+
expect(mutation.fetching.value).toBe(true);
52+
expect(mutation.stale.value).toBe(false);
53+
expect(mutation.error.value).toBe(undefined);
5654

5755
expect(clientMutation).toHaveBeenCalledTimes(1);
5856

5957
subject.next({ data: { test: true }, stale: false });
60-
await promise.then(function () {
61-
expect(mutation.fetching).toBe(false);
62-
expect(mutation.stale).toBe(false);
63-
expect(mutation.error).toBe(undefined);
64-
expect(mutation.data).toEqual({ test: true });
65-
});
58+
59+
await promise;
60+
expect(mutation.fetching.value).toBe(false);
61+
expect(mutation.stale.value).toBe(false);
62+
expect(mutation.error.value).toBe(undefined);
63+
expect(mutation.data.value).toHaveProperty('test', true);
6664
});
6765
});

packages/vue-urql/src/useMutation.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
/* eslint-disable react-hooks/rules-of-hooks */
22

33
import type { Ref } from 'vue';
4-
import { ref, shallowRef } from 'vue';
5-
import type { DocumentNode } from 'graphql';
4+
import { ref } from 'vue';
65
import { pipe, onPush, filter, toPromise, take } from 'wonka';
76

87
import type {
98
Client,
109
AnyVariables,
11-
TypedDocumentNode,
1210
CombinedError,
1311
Operation,
1412
OperationContext,
1513
OperationResult,
14+
DocumentInput,
1615
} from '@urql/core';
17-
import { createRequest } from '@urql/core';
1816

1917
import { useClient } from './useClient';
2018
import type { MaybeRef } from './utils';
21-
import { unref } from './utils';
19+
import { createRequestWithArgs, useRequestState } from './utils';
2220

2321
/** State of the last mutation executed by {@link useMutation}.
2422
*
@@ -126,21 +124,21 @@ export interface UseMutationResponse<T, V extends AnyVariables = AnyVariables> {
126124
* ```
127125
*/
128126
export function useMutation<T = any, V extends AnyVariables = AnyVariables>(
129-
query: TypedDocumentNode<T, V> | DocumentNode | string
127+
query: DocumentInput<T, V>
130128
): UseMutationResponse<T, V> {
131129
return callUseMutation(query);
132130
}
133131

134132
export function callUseMutation<T = any, V extends AnyVariables = AnyVariables>(
135-
query: MaybeRef<TypedDocumentNode<T, V> | DocumentNode | string>,
133+
query: MaybeRef<DocumentInput<T, V>>,
136134
client: Ref<Client> = useClient()
137135
): UseMutationResponse<T, V> {
138136
const data: Ref<T | undefined> = ref();
139-
const stale: Ref<boolean> = ref(false);
140-
const fetching: Ref<boolean> = ref(false);
141-
const error: Ref<CombinedError | undefined> = shallowRef();
142-
const operation: Ref<Operation<T, V> | undefined> = shallowRef();
143-
const extensions: Ref<Record<string, any> | undefined> = shallowRef();
137+
138+
const { fetching, operation, extensions, stale, error } = useRequestState<
139+
T,
140+
V
141+
>();
144142

145143
return {
146144
data,
@@ -157,7 +155,7 @@ export function callUseMutation<T = any, V extends AnyVariables = AnyVariables>(
157155

158156
return pipe(
159157
client.value.executeMutation<T, V>(
160-
createRequest<T, V>(unref(query), unref(variables)),
158+
createRequestWithArgs({ query, variables }),
161159
context || {}
162160
),
163161
onPush(result => {

0 commit comments

Comments
 (0)