Skip to content

Commit

Permalink
Fix useLazyQuery forceUpdate loop regression. (#7715)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn committed Feb 15, 2021
1 parent 2b1f1f4 commit d36595b
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 20 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Apollo Client 3.3.11

### Bug fixes

- Fix `useLazyQuery` `forceUpdate` loop regression introduced by [#7655](https://github.com/apollographql/apollo-client/pull/7655) in version 3.3.10. <br/>
[@benjamn](https://github.com/benjamn) in [#7715](https://github.com/apollographql/apollo-client/pull/7715)

## Apollo Client 3.3.10

### Bug fixes
Expand Down
29 changes: 9 additions & 20 deletions src/react/hooks/utils/useBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,31 @@ export function useBaseQuery<TData = any, TVariables = OperationVariables>(
const updatedOptions = options ? { ...options, query } : { query };

const queryDataRef = useRef<QueryData<TData, TVariables>>();
const queryData =
queryDataRef.current ||
new QueryData<TData, TVariables>({
const queryData = queryDataRef.current || (
queryDataRef.current = new QueryData<TData, TVariables>({
options: updatedOptions as QueryDataOptions<TData, TVariables>,
context,
onNewData() {
if (!queryData.ssrInitiated() && queryDataRef.current) {
if (!queryData.ssrInitiated()) {
// When new data is received from the `QueryData` object, we want to
// force a re-render to make sure the new data is displayed. We can't
// force that re-render if we're already rendering however so to be
// safe we'll trigger the re-render in a microtask.
Promise.resolve().then(forceUpdate);
// safe we'll trigger the re-render in a microtask. In case the
// component gets unmounted before this callback fires, we re-check
// queryDataRef.current before calling forceUpdate().
Promise.resolve().then(() => queryDataRef.current && forceUpdate());
} else {
// If we're rendering on the server side we can force an update at
// any point.
forceUpdate();
}
}
});
})
);

queryData.setOptions(updatedOptions);
queryData.context = context;

// SSR won't trigger the effect hook below that stores the current
// `QueryData` instance for future renders, so we'll handle that here if
// the current render is happening on the server side.
if (queryData.ssrInitiated() && !queryDataRef.current) {
queryDataRef.current = queryData;
}

// `onError` and `onCompleted` callback functions will not always have a
// stable identity, so we'll exclude them from the memoization key to
// prevent `afterExecute` from being triggered un-necessarily.
Expand All @@ -76,12 +71,6 @@ export function useBaseQuery<TData = any, TVariables = OperationVariables>(
: (result as QueryResult<TData, TVariables>);

useEffect(() => {
// We only need one instance of the `QueryData` class, so we'll store it
// as a ref to make it available on subsequent renders.
if (!queryDataRef.current) {
queryDataRef.current = queryData;
}

return () => queryData.cleanup();
}, []);

Expand Down

0 comments on commit d36595b

Please sign in to comment.