Skip to content
This repository has been archived by the owner on Apr 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #314 from teamleadercrm/bugfix/queries-refetch-mem…
Browse files Browse the repository at this point in the history
…ory-leak

Bugfix: queries object fetch memory leak
  • Loading branch information
ArnaudWeyts authored Apr 23, 2020
2 parents 5518c1a + ead48cd commit 77fe9e4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Unreleased

### 🐛 Fixed

* Fixed an issue with the global queries object which caused a memory leak that would duplicate network requests ([ArnaudWeyts](https://github.com/ArnaudWeyts) in [#314](https://github.com/teamleadercrm/react-hooks-api/pull/314))

## [0.1.0-rc12] - 04-03-2020

### 🐛 Fixed
Expand Down
33 changes: 30 additions & 3 deletions src/useQuery/useQuery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useContext, useCallback } from 'react';
import { useEffect, useContext, useCallback, useMemo } from 'react';

import generateQueryCacheKey from '../utils/generateQueryCacheKey';
import useUpdatableState from '../utils/useUpdatableState';
Expand Down Expand Up @@ -26,7 +26,8 @@ type Options = {
fetchAll?: boolean;
};

export const queries: Record<string, { fetch: () => void }> = {};
export const queries: Record<string, { fetch: () => void; _linkedQueriesFetches: Record<string, () => void> }> = {};
let uniqueHookIndex = 0;

const registerQuery = (query: { fetch: () => void } | undefined, fetch: () => void) => {
// A previous query has already been registered, hook up its fetch call as well
Expand Down Expand Up @@ -55,6 +56,12 @@ const useQuery: (query: Query, variables?: any, options?: Options) => any = (
variables,
{ ignoreCache = defaultConfig.ignoreCache, fetchAll = defaultConfig.fetchAll } = defaultConfig,
) => {
const uniqueId = useMemo(() => {
const localIndex = uniqueHookIndex;
uniqueHookIndex++;
return localIndex;
}, []);

const queryKey = generateQueryCacheKey(query(variables));
const [state, setState] = useUpdatableState({
loading: false,
Expand Down Expand Up @@ -159,7 +166,27 @@ const useQuery: (query: Query, variables?: any, options?: Options) => any = (
* so we don't pollute the global scope, but for now, it doesn't hurt
*/
useEffect(() => {
queries[queryKey] = registerQuery(queries[queryKey], () => fetchMore({ variables }));
// Already has a query registered
if (queries[queryKey]) {
queries[queryKey]._linkedQueriesFetches = {
...queries[queryKey]._linkedQueriesFetches,
[uniqueId]: (): void => fetchMore({ variables }),
};
} else {
queries[queryKey] = {
fetch: (): void => {
Object.values(queries[queryKey]?._linkedQueriesFetches || []).forEach(fetch => fetch());
},
_linkedQueriesFetches: {
...queries[queryKey]?._linkedQueriesFetches,
[uniqueId]: (): void => fetchMore({ variables }),
},
};
}

return function cleanup() {
delete queries[queryKey]?._linkedQueriesFetches?.[uniqueId];
};
}, [queryKey]);

return { ...state, fetchMore };
Expand Down

0 comments on commit 77fe9e4

Please sign in to comment.