Skip to content

Commit d30ddf2

Browse files
feat(hooks): align useMutation with rest of the hooks by returning refs (#22)
1 parent 9b0bbb5 commit d30ddf2

File tree

2 files changed

+85
-52
lines changed

2 files changed

+85
-52
lines changed

src/useMutation.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
1-
import { onUnmounted, reactive, watchEffect } from "vue-demi";
2-
import { MutateOptions, MutationObserver } from "react-query/core";
1+
import {
2+
onUnmounted,
3+
reactive,
4+
watchEffect,
5+
readonly,
6+
ToRefs,
7+
toRefs,
8+
} from "vue-demi";
9+
import {
10+
MutateOptions,
11+
MutationObserver,
12+
MutationObserverResult,
13+
} from "react-query/core";
314
import {
415
UseMutationOptions,
5-
UseMutationResult,
616
MutationFunction,
717
MutationKey,
18+
UseMutateFunction,
19+
UseMutateAsyncFunction,
820
} from "react-query/types";
921
import { parseMutationArgs, updateState } from "./utils";
1022
import { useQueryClient } from "./useQueryClient";
1123

24+
type MutationResult<TData, TError, TVariables, TContext> = Omit<
25+
MutationObserverResult<TData, TError, TVariables, TContext>,
26+
"mutate"
27+
>;
28+
29+
export type UseMutationReturnType<
30+
TData,
31+
TError,
32+
TVariables,
33+
TContext,
34+
Result = MutationResult<TData, TError, TVariables, TContext>
35+
> = ToRefs<Readonly<Result>> & {
36+
mutate: UseMutateFunction<TData, TError, TVariables, TContext>;
37+
mutateAsync: UseMutateAsyncFunction<TData, TError, TVariables, TContext>;
38+
};
39+
1240
export function useMutation<
1341
TData = unknown,
1442
TError = unknown,
1543
TVariables = void,
1644
TContext = unknown
1745
>(
1846
options: UseMutationOptions<TData, TError, TVariables, TContext>
19-
): UseMutationResult<TData, TError, TVariables, TContext>;
47+
): UseMutationReturnType<TData, TError, TVariables, TContext>;
2048
export function useMutation<
2149
TData = unknown,
2250
TError = unknown,
@@ -25,7 +53,7 @@ export function useMutation<
2553
>(
2654
mutationFn: MutationFunction<TData, TVariables>,
2755
options?: UseMutationOptions<TData, TError, TVariables, TContext>
28-
): UseMutationResult<TData, TError, TVariables, TContext>;
56+
): UseMutationReturnType<TData, TError, TVariables, TContext>;
2957
export function useMutation<
3058
TData = unknown,
3159
TError = unknown,
@@ -34,7 +62,7 @@ export function useMutation<
3462
>(
3563
mutationKey: MutationKey,
3664
options?: UseMutationOptions<TData, TError, TVariables, TContext>
37-
): UseMutationResult<TData, TError, TVariables, TContext>;
65+
): UseMutationReturnType<TData, TError, TVariables, TContext>;
3866
export function useMutation<
3967
TData = unknown,
4068
TError = unknown,
@@ -44,7 +72,7 @@ export function useMutation<
4472
mutationKey: MutationKey,
4573
mutationFn?: MutationFunction<TData, TVariables>,
4674
options?: UseMutationOptions<TData, TError, TVariables, TContext>
47-
): UseMutationResult<TData, TError, TVariables, TContext>;
75+
): UseMutationReturnType<TData, TError, TVariables, TContext>;
4876
export function useMutation<
4977
TData = unknown,
5078
TError = unknown,
@@ -59,7 +87,7 @@ export function useMutation<
5987
| MutationFunction<TData, TVariables>
6088
| UseMutationOptions<TData, TError, TVariables, TContext>,
6189
arg3?: UseMutationOptions<TData, TError, TVariables, TContext>
62-
): UseMutationResult<TData, TError, TVariables, TContext> {
90+
): UseMutationReturnType<TData, TError, TVariables, TContext> {
6391
const options = parseMutationArgs(arg1, arg2, arg3);
6492
const queryClient = useQueryClient();
6593
const observer = new MutationObserver(queryClient, options);
@@ -75,7 +103,7 @@ export function useMutation<
75103

76104
const mutate = (
77105
variables: TVariables,
78-
mutateOptions: MutateOptions<TData, TError, TVariables, TContext>
106+
mutateOptions?: MutateOptions<TData, TError, TVariables, TContext>
79107
) => {
80108
// eslint-disable-next-line @typescript-eslint/no-empty-function
81109
observer.mutate(variables, mutateOptions).catch(() => {});
@@ -89,8 +117,13 @@ export function useMutation<
89117
unsubscribe();
90118
});
91119

92-
return Object.assign(state, {
120+
const resultRefs = toRefs(readonly(state)) as ToRefs<
121+
Readonly<MutationObserverResult<TData, TError, TVariables, TContext>>
122+
>;
123+
124+
return {
125+
...resultRefs,
93126
mutate,
94127
mutateAsync: state.mutate,
95-
}) as UseMutationResult<TData, TError, TVariables, TContext>;
128+
};
96129
}

tests/useMutation.test.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ describe("useMutation", () => {
2323
const mutation = useMutation((params) => successMutator(params));
2424

2525
expect(mutation).toMatchObject({
26-
isIdle: true,
27-
isLoading: false,
28-
isError: false,
29-
isSuccess: false,
26+
isIdle: { value: true },
27+
isLoading: { value: false },
28+
isError: { value: false },
29+
isSuccess: { value: false },
3030
});
3131
});
3232

@@ -37,12 +37,12 @@ describe("useMutation", () => {
3737
mutation.mutate(result);
3838

3939
expect(mutation).toMatchObject({
40-
isIdle: false,
41-
isLoading: true,
42-
isError: false,
43-
isSuccess: false,
44-
data: undefined,
45-
error: null,
40+
isIdle: { value: false },
41+
isLoading: { value: true },
42+
isError: { value: false },
43+
isSuccess: { value: false },
44+
data: { value: undefined },
45+
error: { value: null },
4646
});
4747
});
4848

@@ -54,12 +54,12 @@ describe("useMutation", () => {
5454
await flushPromises(10);
5555

5656
expect(mutation).toMatchObject({
57-
isIdle: false,
58-
isLoading: false,
59-
isError: true,
60-
isSuccess: false,
61-
data: undefined,
62-
error: Error("Some error"),
57+
isIdle: { value: false },
58+
isLoading: { value: false },
59+
isError: { value: true },
60+
isSuccess: { value: false },
61+
data: { value: undefined },
62+
error: { value: Error("Some error") },
6363
});
6464
});
6565

@@ -72,12 +72,12 @@ describe("useMutation", () => {
7272
await flushPromises(10);
7373

7474
expect(mutation).toMatchObject({
75-
isIdle: false,
76-
isLoading: false,
77-
isError: false,
78-
isSuccess: true,
79-
data: "Mock data",
80-
error: null,
75+
isIdle: { value: false },
76+
isLoading: { value: false },
77+
isError: { value: false },
78+
isSuccess: { value: true },
79+
data: { value: "Mock data" },
80+
error: { value: null },
8181
});
8282
});
8383

@@ -88,15 +88,15 @@ describe("useMutation", () => {
8888

8989
await flushPromises(10);
9090

91-
mutation.reset();
91+
mutation.reset.value();
9292

9393
expect(mutation).toMatchObject({
94-
isIdle: true,
95-
isLoading: false,
96-
isError: false,
97-
isSuccess: false,
98-
data: undefined,
99-
error: null,
94+
isIdle: { value: true },
95+
isLoading: { value: false },
96+
isError: { value: false },
97+
isSuccess: { value: false },
98+
data: { value: undefined },
99+
error: { value: null },
100100
});
101101
});
102102

@@ -218,12 +218,12 @@ describe("useMutation", () => {
218218
await expect(mutation.mutateAsync(result)).resolves.toBe(result);
219219

220220
expect(mutation).toMatchObject({
221-
isIdle: false,
222-
isLoading: false,
223-
isError: false,
224-
isSuccess: true,
225-
data: "Mock data",
226-
error: null,
221+
isIdle: { value: false },
222+
isLoading: { value: false },
223+
isError: { value: false },
224+
isSuccess: { value: true },
225+
data: { value: "Mock data" },
226+
error: { value: null },
227227
});
228228
});
229229

@@ -233,12 +233,12 @@ describe("useMutation", () => {
233233
await expect(mutation.mutateAsync()).rejects.toThrowError("Some error");
234234

235235
expect(mutation).toMatchObject({
236-
isIdle: false,
237-
isLoading: false,
238-
isError: true,
239-
isSuccess: false,
240-
data: undefined,
241-
error: Error("Some error"),
236+
isIdle: { value: false },
237+
isLoading: { value: false },
238+
isError: { value: true },
239+
isSuccess: { value: false },
240+
data: { value: undefined },
241+
error: { value: Error("Some error") },
242242
});
243243
});
244244
});

0 commit comments

Comments
 (0)