Skip to content

Commit

Permalink
feat(react-query): add support for global onSuccess for mutation (#5668)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomer-yechiel committed Apr 28, 2024
1 parent 7f7c36e commit 3bb7111
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"superjson": "^1.12.4",
"ts-prune": "^0.10.3",
"tsx": "^4.0.0",
"turbo": "^1.10.2",
"turbo": "^1.13.2",
"typescript": "^5.4.0",
"vite": "^5.1.0",
"vitest": "^1.2.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,10 @@ export function createRootHooks<
const queryClient = useQueryClient();

const mutationKey = [path];
const defaultOpts = queryClient.getMutationDefaults(mutationKey);

const defaultOpts = queryClient.defaultMutationOptions(
queryClient.getMutationDefaults(mutationKey),
);

const hook = __useMutation(
{
Expand Down
149 changes: 149 additions & 0 deletions packages/tests/server/react/queryClientDefaults.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { routerToServerAndClientNew } from '../___testHelpers';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createTRPCReact, getUntypedClient } from '@trpc/react-query';
import { initTRPC } from '@trpc/server';
import { konn } from 'konn';
import type { ReactNode } from 'react';
import React from 'react';
import { z } from 'zod';

describe('query client defaults', () => {
const ctx = konn()
.beforeEach(() => {
const t = initTRPC.create();
interface Post {
title: string;
}
const onSuccessSpy = vi.fn();

const posts: Post[] = [];

const appRouter = t.router({
list: t.procedure.query(() => posts),
add: t.procedure.input(z.string()).mutation(({ input }) => {
posts.push({
title: input,
});
}),
});
const opts = routerToServerAndClientNew(appRouter);
const trpc = createTRPCReact<typeof appRouter>();

const queryClient = new QueryClient({
defaultOptions: {
mutations: {
onSuccess: async (opts) => {
await queryClient.invalidateQueries();
onSuccessSpy(opts);
},
},
},
});

function App(props: { children: ReactNode }) {
return (
<trpc.Provider
{...{ queryClient, client: getUntypedClient(opts.client) }}
>
<QueryClientProvider client={queryClient}>
{props.children}
</QueryClientProvider>
</trpc.Provider>
);
}
return {
...opts,
App,
trpc,
onSuccessSpy,
};
})
.afterEach(async (opts) => {
await opts?.close?.();
})
.done();

test('clear cache on every mutation', async () => {
const { trpc } = ctx;
const nonce = `nonce-${Math.random()}`;
function MyComp() {
const listQuery = trpc.list.useQuery();
const mutation = trpc.add.useMutation();

return (
<>
<button
onClick={() => {
mutation.mutate(nonce);
}}
data-testid="add"
>
add
</button>
<pre>{JSON.stringify(listQuery.data ?? null, null, 4)}</pre>
</>
);
}

const $ = render(
<ctx.App>
<MyComp />
</ctx.App>,
);

await userEvent.click($.getByTestId('add'));

await waitFor(() => {
expect($.container).toHaveTextContent(nonce);
});
});

test('skip invalidate', async () => {
const { trpc } = ctx;
const nonce = `nonce-${Math.random()}`;
const onSuccessLocalSpy = vi.fn().mockReturnValue('something');

function MyComp() {
const listQuery = trpc.list.useQuery();
const mutation = trpc.add.useMutation({
onSuccess: () => onSuccessLocalSpy(),
});

return (
<>
<button
onClick={() => {
mutation.mutate(nonce);
}}
data-testid="add"
>
add
</button>
<pre>{JSON.stringify(listQuery.data ?? null, null, 4)}</pre>
</>
);
}

const $ = render(
<ctx.App>
<MyComp />
</ctx.App>,
);

await userEvent.click($.getByTestId('add'));

await waitFor(() => {
expect(ctx.onSuccessSpy).not.toHaveBeenCalled();
});

await waitFor(() => {
expect(onSuccessLocalSpy).toHaveBeenCalledTimes(1);
});

await waitFor(() => {
expect($.container).not.toHaveTextContent(nonce);
});
});
});
45 changes: 22 additions & 23 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3bb7111

Please sign in to comment.