Skip to content

Commit

Permalink
fix useLazyQuery not refetching with the correct variables when execu…
Browse files Browse the repository at this point in the history
…te is called multiple times

Fixes #7396
  • Loading branch information
brainkim committed Aug 16, 2021
1 parent d7365da commit ce39d28
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 12 deletions.
81 changes: 79 additions & 2 deletions src/react/hooks/__tests__/useLazyQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
});
Expand Down Expand Up @@ -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 }) => (
<MockedProvider mocks={mocks}>
{children}
</MockedProvider>
),
}
);

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);
});
});
20 changes: 10 additions & 10 deletions src/react/hooks/useLazyQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function useLazyQuery<TData = any, TVariables = OperationVariables>(
>((lazyOptions?: QueryLazyOptions<TVariables>) => {
setExecution((execution) => {
if (execution.called) {
result && result.refetch(lazyOptions);
result && result.refetch(lazyOptions?.variables);
}

return { called: true, lazyOptions };
Expand All @@ -43,6 +43,15 @@ export function useLazyQuery<TData = any, TVariables = OperationVariables>(
});

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];
Expand All @@ -52,15 +61,6 @@ export function useLazyQuery<TData = any, TVariables = OperationVariables>(
};
}
}

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
Expand Down

0 comments on commit ce39d28

Please sign in to comment.