From ba9313c039ba234cb69549f5604cdb0f0a278005 Mon Sep 17 00:00:00 2001 From: iamchanii Date: Mon, 22 Nov 2021 17:38:30 +0900 Subject: [PATCH] feat: use queryFnArgs in getQueryData, setQueryData --- .changeset/big-frogs-hang.md | 5 ++ src/QueryHelper.test.ts | 93 +++++++++--------------------------- src/QueryHelper.ts | 57 ++++++++++++++-------- 3 files changed, 65 insertions(+), 90 deletions(-) create mode 100644 .changeset/big-frogs-hang.md diff --git a/.changeset/big-frogs-hang.md b/.changeset/big-frogs-hang.md new file mode 100644 index 0000000..e6d187e --- /dev/null +++ b/.changeset/big-frogs-hang.md @@ -0,0 +1,5 @@ +--- +'react-query-helper': patch +--- + +Use queryFnArgs in getQueryData, setQueryData and remove undefined args filter logic diff --git a/src/QueryHelper.test.ts b/src/QueryHelper.test.ts index 42b1b89..828e4b1 100644 --- a/src/QueryHelper.test.ts +++ b/src/QueryHelper.test.ts @@ -34,6 +34,11 @@ const getPosts = new QueryHelper( (payload?: { after?: string; first?: number }) => [] as Post[] ); +const getPostById = new QueryHelper( + ['post'], + (id?: number) => ({ id, title: `Post#${id}` } as Post) +); + it('should throw error if QueryHelper.setQueryClient not have been called', () => { // NOTE: Is this right method? QueryHelper.setQueryClient(null as any); @@ -46,7 +51,7 @@ it('should throw error if QueryHelper.setQueryClient not have been called', () = }); describe('getQueryData', () => { - beforeEach(() => { + it('should get access query data', () => { queryClient.setQueryData( ['posts'], [ @@ -54,9 +59,7 @@ describe('getQueryData', () => { { id: 2, title: 'bar' }, ] ); - }); - it('should get posts query data', () => { expect(getPosts.getQueryData()).toMatchInlineSnapshot(` Array [ Object { @@ -70,18 +73,29 @@ describe('getQueryData', () => { ] `); }); + + it('should get access query data with parameter', () => { + queryClient.setQueryData(['post', 1], { id: 1, title: 'foo' }); + + expect(getPostById.getQueryData(1)).toMatchInlineSnapshot(` + Object { + "id": 1, + "title": "foo", + } + `); + }); }); describe('setQueryData', () => { it('should set posts query data', () => { expect(getPosts.getQueryData()).toMatchInlineSnapshot(`undefined`); - getPosts.setQueryData([ + getPosts.setQueryData(undefined, [ { id: 1, title: 'foo' }, { id: 2, title: 'bar' }, ]); - expect(getPosts.getQueryData()).toMatchInlineSnapshot(` + expect(getPosts.getQueryData(undefined)).toMatchInlineSnapshot(` Array [ Object { "id": 1, @@ -96,9 +110,9 @@ describe('setQueryData', () => { }); it('should set posts query data as function', () => { - getPosts.setQueryData([{ id: 1, title: 'foo' }]); + getPosts.setQueryData(undefined, [{ id: 1, title: 'foo' }]); - expect(getPosts.getQueryData()).toMatchInlineSnapshot(` + expect(getPosts.getQueryData(undefined)).toMatchInlineSnapshot(` Array [ Object { "id": 1, @@ -107,7 +121,7 @@ describe('setQueryData', () => { ] `); - getPosts.setQueryData((oldData) => { + getPosts.setQueryData(undefined, (oldData) => { if (!oldData) { return []; } @@ -115,7 +129,7 @@ describe('setQueryData', () => { return [...oldData, { id: 2, title: 'bar' }, { id: 3, title: 'baz' }]; }); - expect(getPosts.getQueryData()).toMatchInlineSnapshot(` + expect(getPosts.getQueryData(undefined)).toMatchInlineSnapshot(` Array [ Object { "id": 1, @@ -134,11 +148,6 @@ describe('setQueryData', () => { }); }); -const getPostById = new QueryHelper( - ['post'], - (id?: number) => ({ id, title: `Post#${id}` } as Post) -); - describe('useQuery', () => { it('should call useQuery with queryKey based on argument', () => { const useGetPostById = getPostById.createQuery(); @@ -157,33 +166,6 @@ describe('useQuery', () => { `); }); - it('should use only baseQueryKey if argument is not defined or undefined', () => { - const useGetPostById = getPostById.createQuery(); - useGetPostById(); - useGetPostById(undefined); - - expect((useQuery as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "queryFn": [Function], - "queryKey": Array [ - "post", - ], - }, - ] - `); - expect((useQuery as jest.Mock).mock.calls[1]).toMatchInlineSnapshot(` - Array [ - Object { - "queryFn": [Function], - "queryKey": Array [ - "post", - ], - }, - ] - `); - }); - it('should call useQuery with options from last argument', () => { const useGetPostById = getPostById.createQuery(); useGetPostById(2, { enabled: true, suspense: true }); @@ -247,35 +229,6 @@ describe('useInfiniteQuery', () => { `); }); - it('should use only baseQueryKey if argument is not defined or undefined', () => { - const useGetPosts = getPosts.createInfiniteQuery(); - useGetPosts(); - useGetPosts(undefined); - - expect((useInfiniteQuery as jest.Mock).mock.calls[0]) - .toMatchInlineSnapshot(` - Array [ - Object { - "queryFn": [Function], - "queryKey": Array [ - "posts", - ], - }, - ] - `); - expect((useInfiniteQuery as jest.Mock).mock.calls[1]) - .toMatchInlineSnapshot(` - Array [ - Object { - "queryFn": [Function], - "queryKey": Array [ - "posts", - ], - }, - ] - `); - }); - it('should call useInfiniteQuery with options from last argument', () => { const useGetPosts = getPosts.createInfiniteQuery(); useGetPosts({ after: '', first: 10 }, { enabled: true, suspense: true }); diff --git a/src/QueryHelper.ts b/src/QueryHelper.ts index fe1b42d..8a13ee8 100644 --- a/src/QueryHelper.ts +++ b/src/QueryHelper.ts @@ -1,9 +1,9 @@ import type { QueryClient, - UseQueryOptions, UseInfiniteQueryOptions, + UseQueryOptions, } from 'react-query'; -import { useQuery, useInfiniteQuery } from 'react-query'; +import { useInfiniteQuery, useQuery } from 'react-query'; import { QueryFilters } from 'react-query/types/core/utils'; type Awaited = T extends Promise ? U : T; @@ -33,6 +33,19 @@ export class QueryHelper< private baseQueryKey: unknown[]; private queryFn: TQueryFn; + private splitArgs( + args: unknown[] + ): [TQueryFnArgs, TRestArgs] { + const queryFnArgs = args.slice(0, this.queryFn.length) as TQueryFnArgs; + const restArgs = args.slice(this.queryFn.length) as TRestArgs; + + return [queryFnArgs, restArgs]; + } + + private getQueryKey(queryFnArgs: TQueryFnArgs) { + return [...this.baseQueryKey, ...queryFnArgs]; + } + constructor(baseQueryKey: unknown[], queryFn: TQueryFn) { this.baseQueryKey = baseQueryKey; this.queryFn = queryFn; @@ -45,15 +58,11 @@ export class QueryHelper< options?: UseQueryOptions ] ) => { - const queryFnArgs = args - .slice(0, this.queryFn.length) - .filter((arg) => arg !== undefined) as TQueryFnArgs; - const options = args.slice(this.queryFn.length)[0] as - | UseQueryOptions - | undefined; + const [queryFnArgs, [options]] = + this.splitArgs<[UseQueryOptions]>(args); return useQuery({ - queryKey: [...this.baseQueryKey, ...queryFnArgs], + queryKey: this.getQueryKey(queryFnArgs), // TODO: how to handle QueryFunctionContext? should it causes breaking changes? queryFn: () => this.queryFn.apply(null, queryFnArgs) as TQueryFnResult, ...defaultUseQueryOptions, @@ -71,15 +80,11 @@ export class QueryHelper< options?: UseInfiniteQueryOptions ] ) => { - const queryFnArgs = args - .slice(0, this.queryFn.length) - .filter((arg) => arg !== undefined) as TQueryFnArgs; - const options = args.slice(this.queryFn.length)[0] as - | UseInfiniteQueryOptions - | undefined; + const [queryFnArgs, [options]] = + this.splitArgs<[UseInfiniteQueryOptions]>(args); return useInfiniteQuery({ - queryKey: [...this.baseQueryKey, ...queryFnArgs], + queryKey: this.getQueryKey(queryFnArgs), // TODO: how to handle QueryFunctionContext? should it causes breaking changes? queryFn: () => this.queryFn.apply(null, queryFnArgs) as TQueryFnResult, ...defaultUseInfiniteQueryOptions, @@ -88,13 +93,25 @@ export class QueryHelper< }; } - getQueryData(filters?: QueryFilters) { + getQueryData( + ...args: [...queryFnArgs: TQueryFnArgs, filters?: QueryFilters] + ) { + const [queryFnArgs, [filters]] = this.splitArgs<[QueryFilters]>(args); const queryClient = this.getQueryClient(); - return queryClient.getQueryData(this.baseQueryKey, filters); + + return queryClient.getQueryData( + this.getQueryKey(queryFnArgs), + filters + ); } - setQueryData(updater: Updater) { + setQueryData( + ...args: [...queryFnArgs: TQueryFnArgs, updater: Updater] + ) { + const [queryFnArgs, [updater]] = + this.splitArgs<[Updater]>(args); const queryClient = this.getQueryClient(); - return queryClient.setQueryData(this.baseQueryKey, updater); + + return queryClient.setQueryData(this.getQueryKey(queryFnArgs), updater); } }