From 3362d442e313696cd912ac6ad4060fd1b2918564 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Fri, 13 Aug 2021 15:29:04 -0400 Subject: [PATCH] fix useLazyQuery not refetching with the correct variables when execute is called multiple times Fixes #7396 --- .../hooks/__tests__/useLazyQuery.test.tsx | 81 ++++++++++++++++++- src/react/hooks/useLazyQuery.ts | 20 ++--- 2 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index 81f58cfb638..fb36a142ff5 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -212,10 +212,9 @@ describe('useLazyQuery Hook', () => { setTimeout(() => execute({ variables: { id: 2 } })); await waitForNextUpdate(); - expect(result.current[1].loading).toBe(true); - await waitForNextUpdate(); + await waitForNextUpdate(); expect(result.current[1].loading).toBe(false); expect(result.current[1].data).toEqual({ hello: 'world 2' }); }); @@ -381,4 +380,82 @@ describe('useLazyQuery Hook', () => { result.current[1].stopPolling(); await expect(waitForNextUpdate({ timeout: 20 })).rejects.toThrow('Timed out'); }); + + it('should persist previous data when a query is re-run and variable changes', async () => { + const CAR_QUERY_BY_ID = gql` + query($id: Int) { + car(id: $id) { + make + model + } + } + `; + + const data1 = { + car: { + make: 'Audi', + model: 'A4', + __typename: 'Car', + }, + }; + + const data2 = { + car: { + make: 'Audi', + model: 'RS8', + __typename: 'Car', + }, + }; + + const mocks = [ + { + request: { query: CAR_QUERY_BY_ID, variables: { id: 1 } }, + result: { data: data1 }, + delay: 20, + }, + { + request: { query: CAR_QUERY_BY_ID, variables: { id: 2 } }, + result: { data: data2 }, + delay: 20, + }, + ]; + + const { result, waitForNextUpdate } = renderHook( + () => useLazyQuery(CAR_QUERY_BY_ID), + { + wrapper: ({ children }) => ( + + {children} + + ), + } + ); + + expect(result.current[1].loading).toBe(false); + expect(result.current[1].data).toBe(undefined); + expect(result.current[1].previousData).toBe(undefined); + const execute = result.current[0]; + setTimeout(() => execute({ variables: { id: 1 }})); + + await waitForNextUpdate(); + expect(result.current[1].loading).toBe(true); + expect(result.current[1].data).toBe(undefined); + expect(result.current[1].previousData).toBe(undefined); + + await waitForNextUpdate(); + expect(result.current[1].loading).toBe(false); + expect(result.current[1].data).toEqual(data1); + expect(result.current[1].previousData).toBe(undefined); + + setTimeout(() => execute({ variables: { id: 2 }})); + await waitForNextUpdate(); + expect(result.current[1].loading).toBe(true); + expect(result.current[1].data).toBe(undefined); + expect(result.current[1].previousData).toEqual(data1); + + await waitForNextUpdate(); + expect(result.current[1].loading).toBe(false); + expect(result.current[1].data).toEqual(data2); + expect(result.current[1].previousData).toEqual(data1); + }); }); diff --git a/src/react/hooks/useLazyQuery.ts b/src/react/hooks/useLazyQuery.ts index 1762d11694b..524c1214e1e 100644 --- a/src/react/hooks/useLazyQuery.ts +++ b/src/react/hooks/useLazyQuery.ts @@ -26,7 +26,7 @@ export function useLazyQuery( >((lazyOptions?: QueryLazyOptions) => { setExecution((execution) => { if (execution.called) { - result && result.refetch(lazyOptions); + result && result.refetch(lazyOptions?.variables); } return { called: true, lazyOptions }; @@ -43,6 +43,15 @@ export function useLazyQuery( }); if (!execution.called) { + result = { + ...result, + loading: false, + data: void 0 as unknown as TData, + error: void 0, + // TODO: fix the type of result + called: false as any, + }; + for (const key in result) { if (typeof (result as any)[key] === 'function') { const method = (result as any)[key]; @@ -52,15 +61,6 @@ export function useLazyQuery( }; } } - - result = { - ...result, - loading: false, - data: void 0 as unknown as TData, - error: void 0, - // TODO: fix the type of result - called: false as any, - }; } // TODO: fix the type of result