@pixotope/query 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/factories.ts CHANGED
@@ -11,7 +11,7 @@ export type MutationInfo<TData, TError, TParams> = {
11
11
 
12
12
  type FnToParamsBase = Record<string, MutationInfo<unknown, unknown, unknown>>;
13
13
 
14
- export type TPromiseFunction<TResponse, TParams> = (
14
+ export type TPromiseFunction<TResponse, TParams, TExtraParams> = (
15
15
  args: Omit<
16
16
  ZMQClient.Call<
17
17
  TResponse,
@@ -22,7 +22,9 @@ export type TPromiseFunction<TResponse, TParams> = (
22
22
  }
23
23
  >,
24
24
  "id"
25
- >
25
+ > & {
26
+ meta?: TExtraParams;
27
+ }
26
28
  ) => Promise<TResponse>;
27
29
 
28
30
  const useCallMutationBase = <
@@ -30,48 +32,53 @@ const useCallMutationBase = <
30
32
  TData = unknown,
31
33
  TError = unknown,
32
34
  TParams = unknown,
35
+ TMetadata = unknown,
33
36
  >(
34
- promiseFunc: TPromiseFunction<TData, TParams>,
37
+ promiseFunc: TPromiseFunction<TData, TParams, TMetadata>,
35
38
  functionName: keyof TFnToParams,
36
- service: string,
37
- options?: Omit<MutationOptions<TData, TError, TParams>, "mutationFn"> & {
38
- avoidTimeout?: boolean;
39
- customTimeout?: number;
40
- }
39
+ service: (meta?: TMetadata) => string,
40
+ options?: Omit<
41
+ MutationOptions<TData, TError, TParams, TMetadata>,
42
+ "mutationFn"
43
+ >
41
44
  ) => {
42
- const {
43
- avoidTimeout = true,
44
- customTimeout = undefined,
45
- ...rest
46
- } = useMemo(() => options ?? {}, [options]);
45
+ const timeout = options?.timeout;
46
+ const { ...rest } = useMemo(() => options ?? {}, [options]);
47
47
  const mutationFn = useCallback(
48
- async (parameters: TParams) => {
48
+ async (parameters: TParams, meta?: TMetadata) => {
49
49
  try {
50
50
  return await promiseFunc({
51
- service,
51
+ service: service(meta),
52
52
  functionName: functionName.toString(),
53
53
  parameters,
54
54
  options: {
55
- avoidTimeout,
56
- customTimeout,
55
+ avoidTimeout: !timeout,
56
+ customTimeout: timeout,
57
57
  },
58
+ meta,
58
59
  });
59
- } catch (e: any) {
60
- throw e.message;
60
+ } catch (e) {
61
+ if (e instanceof Error) {
62
+ throw e;
63
+ }
64
+ throw new Error(e as string);
61
65
  }
62
66
  },
63
- [avoidTimeout, customTimeout, functionName, service]
67
+ [functionName, service, timeout]
64
68
  );
65
69
 
66
- return useMutation<TData, TError, TParams>({
70
+ return useMutation<TData, TError, TParams, TMetadata>({
67
71
  mutationFn,
68
72
  ...rest,
69
73
  });
70
74
  };
71
75
 
72
- export function buildMutationHook<TFnToParams extends FnToParamsBase>(
73
- promiseFunc: TPromiseFunction<unknown, unknown>,
74
- genTargetService: (machine: string | undefined) => string
76
+ export function buildMutationHook<
77
+ TFnToParams extends FnToParamsBase,
78
+ TMetadata = unknown,
79
+ >(
80
+ promiseFunc: TPromiseFunction<unknown, unknown, unknown>,
81
+ genTargetService: (meta?: TMetadata) => string
75
82
  ) {
76
83
  return function useCallMutationBuilder<TFn extends keyof TFnToParams>(
77
84
  func: TFn,
@@ -80,18 +87,18 @@ export function buildMutationHook<TFnToParams extends FnToParamsBase>(
80
87
  TFnToParams,
81
88
  TFnToParams[TFn]["data"],
82
89
  TFnToParams[TFn]["error"],
83
- TFnToParams[TFn]["params"]
90
+ TFnToParams[TFn]["params"],
91
+ TMetadata
84
92
  >
85
- >[3] & { machine?: string }
93
+ >[3]
86
94
  ) {
87
- const targetService = genTargetService(options?.machine);
88
-
89
95
  return useCallMutationBase<
90
96
  TFnToParams,
91
97
  TFnToParams[TFn]["data"],
92
98
  TFnToParams[TFn]["error"],
93
- TFnToParams[TFn]["params"]
94
- >(promiseFunc, func, targetService, options);
99
+ TFnToParams[TFn]["params"],
100
+ TMetadata
101
+ >(promiseFunc, func, genTargetService, options);
95
102
  };
96
103
  }
97
104
 
@@ -101,32 +108,30 @@ const useCallQueryBase = <
101
108
  TError = unknown,
102
109
  TParams = unknown,
103
110
  TSelect = TData,
111
+ TMetadata = unknown,
104
112
  >(
105
- promiseFunction: TPromiseFunction<TData, TParams>,
113
+ promiseFunction: TPromiseFunction<TData, TParams, TMetadata>,
106
114
  functionName: keyof TFnToParams,
107
115
  params: TParams,
108
- service: string,
116
+ service: (meta?: TMetadata) => string,
109
117
  options?: Omit<QueryOptions<TData, TError, TParams, TSelect>, "queryFn"> & {
110
- avoidTimeout?: boolean;
111
- customTimeout?: number;
118
+ meta?: TMetadata;
112
119
  }
113
120
  ) => {
114
- const {
115
- avoidTimeout = true,
116
- customTimeout = undefined,
117
- ...rest
118
- } = useMemo(() => options ?? {}, [options]);
121
+ const timeout = options?.timeout;
122
+ const { ...rest } = useMemo(() => options ?? {}, [options]);
119
123
  const queryFn = useCallback(
120
- async (refetchParams: TParams | void, overrideTargetMachine?: string) => {
124
+ async (refetchParams: TParams | void) => {
121
125
  try {
122
126
  return await promiseFunction({
123
- service: overrideTargetMachine ?? service,
127
+ service: service(options?.meta),
124
128
  functionName: functionName.toString(),
125
129
  parameters: refetchParams ?? params,
126
130
  options: {
127
- avoidTimeout,
128
- customTimeout,
131
+ avoidTimeout: !timeout,
132
+ customTimeout: timeout,
129
133
  },
134
+ meta: options?.meta,
130
135
  });
131
136
  } catch (e) {
132
137
  if (e instanceof Error) {
@@ -135,7 +140,7 @@ const useCallQueryBase = <
135
140
  throw new Error(e as string);
136
141
  }
137
142
  },
138
- [avoidTimeout, customTimeout, functionName, service, params]
143
+ [functionName, service, params, timeout]
139
144
  );
140
145
 
141
146
  return useQuery<TData, TError, TParams, TSelect>({
@@ -144,9 +149,12 @@ const useCallQueryBase = <
144
149
  });
145
150
  };
146
151
 
147
- export function buildQueryHook<TFnToParams extends FnToParamsBase>(
148
- promiseFunction: TPromiseFunction<unknown, unknown>,
149
- getTargetService: (machine: string | undefined) => string
152
+ export function buildQueryHook<
153
+ TFnToParams extends FnToParamsBase,
154
+ TMetadata = unknown,
155
+ >(
156
+ promiseFunction: TPromiseFunction<unknown, unknown, unknown>,
157
+ getTargetService: (meta?: TMetadata) => string
150
158
  ) {
151
159
  return function useCallQueryBuilder<
152
160
  TFn extends keyof TFnToParams,
@@ -160,18 +168,18 @@ export function buildQueryHook<TFnToParams extends FnToParamsBase>(
160
168
  TFnToParams[TFn]["data"],
161
169
  TFnToParams[TFn]["error"],
162
170
  TFnToParams[TFn]["params"],
163
- TSelect
171
+ TSelect,
172
+ TMetadata
164
173
  >
165
- >[4] & { machine?: string }
174
+ >[4] & { meta?: TMetadata }
166
175
  ) {
167
- const targetService = getTargetService(options?.machine);
168
-
169
176
  return useCallQueryBase<
170
177
  TFnToParams,
171
178
  TFnToParams[TFn]["data"],
172
179
  TFnToParams[TFn]["error"],
173
180
  TFnToParams[TFn]["params"],
174
- TSelect
175
- >(promiseFunction, func, params, targetService, options);
181
+ TSelect,
182
+ TMetadata
183
+ >(promiseFunction, func, params, getTargetService, options);
176
184
  };
177
185
  }
@@ -17,7 +17,9 @@ export function bindClientSocketProxy(socketClientProxy: ZMQProxyWSClient) {
17
17
  }
18
18
 
19
19
  export function bindPromiseFunction(clientSocketProxy: ZMQProxyWSClient) {
20
- return async (...args: Parameters<TPromiseFunction<unknown, unknown>>) => {
20
+ return async (
21
+ ...args: Parameters<TPromiseFunction<unknown, unknown, unknown>>
22
+ ) => {
21
23
  const res = await clientSocketProxy.callAsync(...args);
22
24
  return res.message.Result;
23
25
  };
@@ -0,0 +1,106 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { useMutation } from "./useMutation";
3
+ import { act, renderHook, waitFor } from "@testing-library/react";
4
+
5
+ describe("useMutation", () => {
6
+ it("should be in idle state on mount", () => {
7
+ const { result } = renderHook(() => useMutation({ mutationFn: vi.fn() }));
8
+ expect(result.current.status).toBe("idle");
9
+ });
10
+
11
+ it("should be in loading state after mutationFn is called", async () => {
12
+ const { result } = renderHook(() => useMutation({ mutationFn: vi.fn() }));
13
+ act(() => result.current.mutate({}));
14
+ await waitFor(() => expect(result.current.status).toBe("loading"));
15
+ });
16
+
17
+ it("should be in success state after mutationFn resolves", async () => {
18
+ const { result } = renderHook(() =>
19
+ useMutation({ mutationFn: vi.fn().mockResolvedValue("test") })
20
+ );
21
+ act(() => result.current.mutate({}));
22
+ await waitFor(() => expect(result.current.status).toBe("success"));
23
+ });
24
+
25
+ it("should be in error state after mutationFn rejects", async () => {
26
+ const { result } = renderHook(() =>
27
+ useMutation({ mutationFn: vi.fn().mockRejectedValue("test") })
28
+ );
29
+ act(() => result.current.mutate({}));
30
+ await waitFor(() => expect(result.current.status).toBe("error"));
31
+ });
32
+
33
+ it("should call onSuccess callback after mutationFn resolves", async () => {
34
+ const onSuccess = vi.fn();
35
+ const { result } = renderHook(() =>
36
+ useMutation({ mutationFn: vi.fn().mockResolvedValue("test"), onSuccess })
37
+ );
38
+ act(() => result.current.mutate({}, { onSuccess }));
39
+ await waitFor(() => expect(onSuccess).toBeCalledTimes(2));
40
+ expect(onSuccess).toBeCalledWith("test", {}, undefined);
41
+ });
42
+
43
+ it("should call onError callback after mutationFn rejects", async () => {
44
+ const onError = vi.fn();
45
+ const { result } = renderHook(() =>
46
+ useMutation({ mutationFn: vi.fn().mockRejectedValue("test"), onError })
47
+ );
48
+ act(() => result.current.mutate({}, { onError }));
49
+ await waitFor(() => expect(onError).toBeCalledTimes(2));
50
+ expect(onError).toBeCalledWith("test", {}, undefined);
51
+ });
52
+
53
+ it("should call onSettled callback after mutationFn resolves", async () => {
54
+ const onSettled = vi.fn();
55
+ const { result } = renderHook(() =>
56
+ useMutation({
57
+ mutationFn: vi.fn().mockResolvedValue("test"),
58
+ onSettled,
59
+ })
60
+ );
61
+ act(() => result.current.mutate({}, { onSettled }));
62
+ await waitFor(() => expect(onSettled).toBeCalledTimes(2));
63
+ expect(onSettled).toBeCalledWith("test", null, {}, undefined);
64
+ });
65
+
66
+ it("should call onSettled callback after mutationFn rejects", async () => {
67
+ const onSettled = vi.fn();
68
+ const { result } = renderHook(() =>
69
+ useMutation({ mutationFn: vi.fn().mockRejectedValue("test"), onSettled })
70
+ );
71
+ act(() => result.current.mutate({}, { onSettled }));
72
+ await waitFor(() => expect(onSettled).toBeCalledTimes(2));
73
+ expect(onSettled).toBeCalledWith(undefined, "test", {}, undefined);
74
+ });
75
+
76
+ it("should pass correct params mutationFn and callbacks to mutationFn", async () => {
77
+ const mutationFn = vi.fn();
78
+ const params = { foo: "bar" };
79
+ const { result } = renderHook(() => useMutation({ mutationFn }));
80
+ act(() => result.current.mutate(params));
81
+ await waitFor(() => expect(mutationFn).toBeCalledTimes(1));
82
+ expect(mutationFn).toBeCalledWith(params, undefined);
83
+ });
84
+
85
+ it("should pass meta to mutationFn", async () => {
86
+ const mutationFn = vi.fn();
87
+ const { result } = renderHook(() => useMutation({ mutationFn }));
88
+ act(() => result.current.mutate({}, { meta: { foo: "bar" } }));
89
+ await waitFor(() => expect(mutationFn).toBeCalledTimes(1));
90
+ expect(mutationFn).toBeCalledWith({}, { foo: "bar" });
91
+ });
92
+
93
+ it("should call prepareParams", async () => {
94
+ const prepareParams = vi.fn();
95
+ const { result } = renderHook(() =>
96
+ useMutation({
97
+ mutationFn: vi.fn(),
98
+ prepareParams,
99
+ params: { baz: "baz" },
100
+ })
101
+ );
102
+ act(() => result.current.mutate({}, { meta: { foo: "bar" } }));
103
+ await waitFor(() => expect(prepareParams).toBeCalledTimes(1));
104
+ expect(prepareParams).toBeCalledWith({}, { baz: "baz" }, { foo: "bar" });
105
+ });
106
+ });
@@ -1,40 +1,63 @@
1
1
  import { useCallback, useRef, useState } from "react";
2
2
 
3
- export type MutationFunction<TData = unknown, TParams = unknown> = (
4
- params: TParams,
5
- overrideTargetMachine?: string
6
- ) => Promise<TData>;
3
+ export type MutationFunction<
4
+ TData = unknown,
5
+ TParams = unknown,
6
+ TMetadata = unknown,
7
+ > = (params: TParams, meta?: TMetadata) => Promise<TData>;
7
8
 
8
9
  export interface MutationOptions<
9
10
  TData = unknown,
10
11
  TError = unknown,
11
12
  TParams = void,
13
+ TMetadata = unknown,
12
14
  > {
13
- mutationFn: MutationFunction<TData, TParams>;
15
+ mutationFn: MutationFunction<TData, TParams, TMetadata>;
14
16
  params?: TParams;
15
- onSuccess?: (data: TData, variables: TParams) => Promise<unknown> | unknown;
16
- onError?: (error: TError, variables: TParams) => Promise<unknown> | unknown;
17
+ onSuccess?: (
18
+ data: TData,
19
+ variables: TParams,
20
+ meta?: TMetadata
21
+ ) => Promise<unknown> | unknown;
22
+ onError?: (
23
+ error: TMutationError<TError>,
24
+ variables: TParams,
25
+ meta?: TMetadata
26
+ ) => Promise<unknown> | unknown;
17
27
  onSettled?: (
18
28
  data: TData | undefined,
19
- error: TError | null,
20
- variables: TParams
29
+ error: TMutationError<TError> | null,
30
+ variables: TParams,
31
+ meta?: TMetadata
21
32
  ) => Promise<unknown> | unknown;
22
33
  compareOrThrow?: (result: TData | TError) => boolean;
23
34
  timeout?: number;
24
- prepareParams?: (variables: TParams, defaults?: TParams) => TParams;
35
+ prepareParams?: (
36
+ variables: TParams,
37
+ defaults?: TParams,
38
+ meta?: TMetadata
39
+ ) => TParams;
25
40
  }
26
41
 
42
+ type TMutationError<TError> = TError | Error | null;
43
+
27
44
  export interface MutateOptions<
28
45
  TData = unknown,
29
46
  TError = unknown,
30
47
  TParams = void,
48
+ TMetadata = unknown,
31
49
  > {
32
- onSuccess?: (data: TData, variables: TParams) => void;
33
- onError?: (error: TError, variables: TParams) => void;
50
+ onSuccess?: (data: TData, variables: TParams, meta?: TMetadata) => void;
51
+ onError?: (
52
+ error: TMutationError<TError>,
53
+ variables: TParams,
54
+ meta?: TMetadata
55
+ ) => void;
34
56
  onSettled?: (
35
57
  data: TData | undefined,
36
- error: TError | null,
37
- variables: TParams
58
+ error: TMutationError<TError> | null,
59
+ variables: TParams,
60
+ meta?: TMetadata
38
61
  ) => void;
39
62
  }
40
63
 
@@ -56,54 +79,13 @@ export class ComparisonFailError<TPayload = unknown> extends Error {
56
79
  }
57
80
  }
58
81
 
59
- /**
60
- * `useMutation` is a hook that allows you to perform a mutation/push updates to the services while
61
- * providing extensive API to tap into the status and results of the mutation.
62
- * @param mutationFn The mutation function to be called when the `mutate` function is called.
63
- * `useMutation` does not care about what the function does, all it needs it a function that returns
64
- * a promise.
65
- * @param options Options to configure the mutation.
66
- * @returns An object with the following properties:
67
- * - `mutateAsync`: A function that takes in the variables and returns a promise that resolves to the
68
- * result of the mutation. This function can be awaited to get the result of the mutation. Callbacks can
69
- * be passed to this function to be called when the mutation is successful or when it fails. It's good idea
70
- * to wrap this function in a try/catch block.
71
- * - `mutate`: A function that takes in the variables and returns nothing. This function does not
72
- * return a promise. Callbacks can be passed to this function to be called when the mutation is
73
- * successful or when it fails.
74
- * - `status`: The status of the mutation. Can be one of `idle`, `loading`, `success` or `error`.
75
- * - `result`: The result of the mutation. This is undefined until the mutation is successful.
76
- * - `reset`: A function that resets the mutation to the initial state.
77
- * - `error`: The error object if the mutation has failed.
78
- * @example
79
- * ```typescript
80
- * const mutationRes = useMutation({
81
- * mutationFn: (variables) => {
82
- * return ZMQHelper.callSomethingAsync(variables)
83
- * },
84
- * onSuccess: (data) => {
85
- * // do something with the result
86
- * },
87
- * onError: (error) => {
88
- * // do something with the error
89
- * },
90
- * onSettled: (data, error) => {
91
- * // do something when the mutation is done
92
- * }});
93
- *
94
- * // call the mutation
95
- * const res = await mutationRes.mutateAsync({ foo: "bar" });
96
- * // OR
97
- * mutationRes.mutate({ foo: "bar" }, {
98
- * onSuccess: (data) => {
99
- * // do something with the result
100
- * // for example show a toast message
101
- * // stop local loading state
102
- * });
103
- * ```
104
- */
105
- export const useMutation = <TData = unknown, TError = unknown, TParams = void>(
106
- options: MutationOptions<TData, TError, TParams>
82
+ export const useMutation = <
83
+ TData = unknown,
84
+ TError = TMutationError<unknown>,
85
+ TParams = void,
86
+ TMetadata = unknown,
87
+ >(
88
+ options: MutationOptions<TData, TError, TParams, TMetadata>
107
89
  ) => {
108
90
  const {
109
91
  mutationFn,
@@ -116,7 +98,7 @@ export const useMutation = <TData = unknown, TError = unknown, TParams = void>(
116
98
  timeout,
117
99
  } = options;
118
100
  const [status, setStatus] = useState<MutationStatus>("idle");
119
- const [error, setError] = useState<TError | null>(null);
101
+ const [error, setError] = useState<TMutationError<TError>>(null);
120
102
  const [result, setResult] = useState<TData | undefined>(undefined);
121
103
  const mutationFnRef = useRef(mutationFn);
122
104
  const internalOptionsRef = useRef({
@@ -133,84 +115,77 @@ export const useMutation = <TData = unknown, TError = unknown, TParams = void>(
133
115
  const internalCallbackRef = useRef(internalCallbackRefistry);
134
116
  internalCallbackRef.current = internalCallbackRefistry;
135
117
 
136
- const mutateAsync = useCallback(
137
- async (params: TParams, overrideTargetMachine?: string) => {
138
- setStatus("loading");
139
- setError(null);
140
-
141
- try {
142
- const promises: RacePromises<TData>[] = [
143
- mutationFnRef.current(
144
- internalCallbackRef.current.prepareParams
145
- ? internalCallbackRef.current.prepareParams(
146
- params,
147
- internalOptionsRef.current.params
118
+ const mutateAsync = useCallback(async (params: TParams, meta?: TMetadata) => {
119
+ setStatus("loading");
120
+ setError(null);
121
+
122
+ try {
123
+ const promises: RacePromises<TData>[] = [
124
+ mutationFnRef.current(
125
+ internalCallbackRef.current.prepareParams
126
+ ? internalCallbackRef.current.prepareParams(
127
+ params,
128
+ internalOptionsRef.current.params,
129
+ meta
130
+ )
131
+ : params,
132
+ meta
133
+ ),
134
+ ...(internalOptionsRef.current.timeout
135
+ ? [
136
+ new Promise<RaceErrorReason>((resolve) =>
137
+ setTimeout(
138
+ () => resolve("timeout"),
139
+ internalOptionsRef.current.timeout
148
140
  )
149
- : params,
150
- overrideTargetMachine
151
- ),
152
- ...(internalOptionsRef.current.timeout
153
- ? [
154
- new Promise<RaceErrorReason>((resolve) =>
155
- setTimeout(
156
- () => resolve("timeout"),
157
- internalOptionsRef.current.timeout
158
- )
159
- ),
160
- ]
161
- : []),
162
- ];
163
-
164
- const res = await Promise.race(promises);
165
-
166
- if (res === "timeout") {
167
- throw new Error("timeout");
168
- }
141
+ ),
142
+ ]
143
+ : []),
144
+ ];
169
145
 
170
- if (internalCallbackRef.current.compareOrThrow?.(res)) {
171
- throw new ComparisonFailError(JSON.stringify(res), res);
172
- }
146
+ const res = await Promise.race(promises);
173
147
 
174
- setResult(res);
175
- setStatus("success");
148
+ if (res === "timeout") {
149
+ throw new Error("timeout");
150
+ }
176
151
 
177
- internalCallbackRef.current.onSuccess?.(res, params);
178
- internalCallbackRef.current.onSettled?.(res, null, params);
152
+ if (internalCallbackRef.current.compareOrThrow?.(res)) {
153
+ throw new ComparisonFailError(JSON.stringify(res), res);
154
+ }
179
155
 
180
- return res;
181
- } catch (error: any) {
182
- setError(error);
183
- setStatus("error");
156
+ setResult(res);
157
+ setStatus("success");
184
158
 
185
- if (internalCallbackRef.current.onError) {
186
- internalCallbackRef.current.onError(error, params);
187
- }
159
+ internalCallbackRef.current.onSuccess?.(res, params, meta);
160
+ internalCallbackRef.current.onSettled?.(res, null, params, meta);
188
161
 
189
- if (internalCallbackRef.current.onSettled) {
190
- internalCallbackRef.current.onSettled(undefined, error, params);
191
- }
162
+ return res;
163
+ } catch (error: any) {
164
+ setError(error);
165
+ setStatus("error");
192
166
 
193
- throw error;
194
- }
195
- },
196
- []
197
- );
167
+ internalCallbackRef.current.onError?.(error, params, meta);
168
+ internalCallbackRef.current.onSettled?.(undefined, error, params, meta);
169
+
170
+ throw error;
171
+ }
172
+ }, []);
198
173
 
199
174
  const mutate = useCallback(
200
175
  (
201
176
  variables: TParams,
202
- options?: MutateOptions<TData, TError, TParams> & {
203
- overrideTargetMachine?: string;
177
+ options?: MutateOptions<TData, TError, TParams, TMetadata> & {
178
+ meta?: TMetadata;
204
179
  }
205
180
  ) => {
206
- mutateAsync(variables, options?.overrideTargetMachine).then(
181
+ mutateAsync(variables, options?.meta).then(
207
182
  (data) => {
208
- options?.onSuccess?.(data, variables);
209
- options?.onSettled?.(data, null, variables);
183
+ options?.onSuccess?.(data, variables, options?.meta);
184
+ options?.onSettled?.(data, null, variables, options?.meta);
210
185
  },
211
186
  (error) => {
212
- options?.onError?.(error, variables);
213
- options?.onSettled?.(undefined, error, variables);
187
+ options?.onError?.(error, variables, options?.meta);
188
+ options?.onSettled?.(undefined, error, variables, options?.meta);
214
189
  }
215
190
  );
216
191
  },
@@ -222,7 +197,11 @@ export const useMutation = <TData = unknown, TError = unknown, TParams = void>(
222
197
  status,
223
198
  result,
224
199
  mutate,
225
- reset: () => setStatus("idle"),
200
+ reset: () => {
201
+ setStatus("idle");
202
+ setError(null);
203
+ setResult(undefined);
204
+ },
226
205
  error,
227
206
  };
228
207
  };