Skip to content

Commit ef8b036

Browse files
committed
Changed return type of useMutation when ignoreResult is explicitly set to true to hide unset result
1 parent cfb1ecd commit ef8b036

File tree

3 files changed

+95
-6
lines changed

3 files changed

+95
-6
lines changed

src/react/hooks/__tests__/useMutation.test.tsx

+59-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import {
3838
createRenderStream,
3939
renderHookToSnapshotStream,
4040
} from "@testing-library/react-render-stream";
41-
import { MutationTuple, QueryResult } from "../../types/types";
41+
import { MutationResult, MutationTuple, QueryResult } from "../../types/types";
4242
import { invariant } from "../../../utilities/globals";
4343

4444
describe("useMutation Hook", () => {
@@ -3389,4 +3389,62 @@ describe.skip("Type Tests", () => {
33893389
expectTypeOf(data).toMatchTypeOf<Mutation | null | undefined>();
33903390
expectTypeOf(mutate()).toMatchTypeOf<Promise<FetchResult<Mutation>>>();
33913391
});
3392+
3393+
test("should not be able to access result when using ignoreResults", async () => {
3394+
const mutation = gql`
3395+
mutation {
3396+
updateUser {
3397+
id
3398+
}
3399+
}
3400+
`;
3401+
3402+
type Mutation = {
3403+
updateUser: {
3404+
__typename: "User";
3405+
id: string;
3406+
};
3407+
};
3408+
3409+
// Explicit `true`
3410+
{
3411+
const [mutate, result] = useMutation<Mutation>(mutation, {
3412+
ignoreResults: true,
3413+
});
3414+
expectTypeOf(result).toMatchTypeOf<{ reset: () => void }>();
3415+
expectTypeOf(result).not.toMatchTypeOf<MutationResult<Mutation>>();
3416+
expectTypeOf(mutate()).toMatchTypeOf<Promise<FetchResult<Mutation>>>();
3417+
const {
3418+
reset,
3419+
// @ts-expect-error
3420+
data,
3421+
// @ts-expect-error
3422+
loading,
3423+
// @ts-expect-error
3424+
error,
3425+
} = result;
3426+
reset;
3427+
data;
3428+
loading;
3429+
error;
3430+
}
3431+
3432+
// Explicit `false`
3433+
{
3434+
const [mutate, result] = useMutation<Mutation>(mutation, {
3435+
ignoreResults: false,
3436+
});
3437+
expectTypeOf(result).toMatchTypeOf<MutationResult<Mutation>>();
3438+
expectTypeOf(mutate()).toMatchTypeOf<Promise<FetchResult<Mutation>>>();
3439+
}
3440+
3441+
// Unknown boolean
3442+
{
3443+
const [mutate, result] = useMutation<Mutation>(mutation, {
3444+
ignoreResults: Math.random() > 0.5,
3445+
});
3446+
expectTypeOf(result).toMatchTypeOf<MutationResult<Mutation>>();
3447+
expectTypeOf(mutate()).toMatchTypeOf<Promise<FetchResult<Mutation>>>();
3448+
}
3449+
});
33923450
});

src/react/hooks/useMutation.ts

+33
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from "rehackt";
22
import type { DocumentNode } from "graphql";
33
import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
44
import type {
5+
MutationFunction,
56
MutationFunctionOptions,
67
MutationHookOptions,
78
MutationResult,
@@ -69,6 +70,38 @@ import { useIsomorphicLayoutEffect } from "./internal/useIsomorphicLayoutEffect.
6970
* @param options - Options to control how the mutation is executed.
7071
* @returns A tuple in the form of `[mutate, result]`
7172
*/
73+
export function useMutation<
74+
TData = any,
75+
TVariables = OperationVariables,
76+
TContext = DefaultContext,
77+
TCache extends ApolloCache<any> = ApolloCache<any>,
78+
>(
79+
mutation: DocumentNode | TypedDocumentNode<TData, TVariables>,
80+
options: { ignoreResults: true } & MutationHookOptions<
81+
NoInfer<TData>,
82+
NoInfer<TVariables>,
83+
TContext,
84+
TCache
85+
>
86+
): [
87+
MutationFunction<TData, TVariables, TContext, TCache>,
88+
// result is not reliable when ignoreResults is true
89+
Pick<MutationResult<TData>, "reset">,
90+
];
91+
export function useMutation<
92+
TData = any,
93+
TVariables = OperationVariables,
94+
TContext = DefaultContext,
95+
TCache extends ApolloCache<any> = ApolloCache<any>,
96+
>(
97+
mutation: DocumentNode | TypedDocumentNode<TData, TVariables>,
98+
options?: MutationHookOptions<
99+
NoInfer<TData>,
100+
NoInfer<TVariables>,
101+
TContext,
102+
TCache
103+
>
104+
): MutationTuple<TData, TVariables, TContext, TCache>;
72105
export function useMutation<
73106
TData = any,
74107
TVariables = OperationVariables,

src/react/types/types.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ export declare type MutationFunction<
394394
TCache extends ApolloCache<any> = ApolloCache<any>,
395395
> = (
396396
options?: MutationFunctionOptions<TData, TVariables, TContext, TCache>
397+
// TODO This FetchResult<TData> seems strange here, as opposed to an
398+
// ApolloQueryResult<TData>
397399
) => Promise<FetchResult<MaybeMasked<TData>>>;
398400

399401
export interface MutationHookOptions<
@@ -418,11 +420,7 @@ export type MutationTuple<
418420
TContext = DefaultContext,
419421
TCache extends ApolloCache<any> = ApolloCache<any>,
420422
> = [
421-
mutate: (
422-
options?: MutationFunctionOptions<TData, TVariables, TContext, TCache>
423-
// TODO This FetchResult<TData> seems strange here, as opposed to an
424-
// ApolloQueryResult<TData>
425-
) => Promise<FetchResult<MaybeMasked<TData>>>,
423+
mutate: MutationFunction<TData, TVariables, TContext, TCache>,
426424
result: MutationResult<TData>,
427425
];
428426

0 commit comments

Comments
 (0)