From 834942971c8933068877fba544740ccf693dcb5f Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Thu, 4 Feb 2021 13:20:10 -0500 Subject: [PATCH 1/9] fix: setState after unmount --- src/react/hooks/utils/useBaseQuery.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index 2d5083097e0..c109a76f3ed 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -1,4 +1,4 @@ -import { useContext, useEffect, useReducer, useRef } from 'react'; +import { useContext, useEffect, useReducer, useRef, RefObject } from 'react'; import { DocumentNode } from 'graphql'; import { TypedDocumentNode } from '@graphql-typed-document-node/core'; @@ -13,13 +13,26 @@ import { useDeepMemo } from './useDeepMemo'; import { OperationVariables } from '../../../core'; import { getApolloContext } from '../../context'; +const useMounted = (): RefObject => { + const mounted = useRef(false) + useEffect(() => { + mounted.current = true + return () => { + mounted.current = false + } + }, []) + return mounted +} + export function useBaseQuery( query: DocumentNode | TypedDocumentNode, options?: QueryHookOptions, lazy = false ) { const context = useContext(getApolloContext()); - const [tick, forceUpdate] = useReducer(x => x + 1, 0); + const mounted = useMounted() + const [tick, forceUpdateUnsafe] = useReducer(x => x + 1, 0); + const forceUpdate = () => mounted.current ? forceUpdateUnsafe() : undefined const updatedOptions = options ? { ...options, query } : { query }; const queryDataRef = useRef>(); From 9ef74b121d95bd8cc591e4baf8aa791284ea31a1 Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Thu, 4 Feb 2021 13:38:31 -0500 Subject: [PATCH 2/9] add some semis --- src/react/hooks/utils/useBaseQuery.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index c109a76f3ed..d88bb348039 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -14,14 +14,14 @@ import { OperationVariables } from '../../../core'; import { getApolloContext } from '../../context'; const useMounted = (): RefObject => { - const mounted = useRef(false) + const mounted = useRef(false); useEffect(() => { - mounted.current = true + mounted.current = true; return () => { - mounted.current = false + mounted.current = false; } - }, []) - return mounted + }, []); + return mounted; } export function useBaseQuery( From e2d3323e153b5cbf309d14dd4f0a6014115fdd3e Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Thu, 4 Feb 2021 13:39:31 -0500 Subject: [PATCH 3/9] more semi --- src/react/hooks/utils/useBaseQuery.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index d88bb348039..a73450fb06f 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -30,9 +30,9 @@ export function useBaseQuery( lazy = false ) { const context = useContext(getApolloContext()); - const mounted = useMounted() + const mounted = useMounted(); const [tick, forceUpdateUnsafe] = useReducer(x => x + 1, 0); - const forceUpdate = () => mounted.current ? forceUpdateUnsafe() : undefined + const forceUpdate = () => mounted.current ? forceUpdateUnsafe() : undefined; const updatedOptions = options ? { ...options, query } : { query }; const queryDataRef = useRef>(); From 3b45aebf1912036ffe796e732fe0ee7ed59409ee Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Thu, 4 Feb 2021 14:16:28 -0500 Subject: [PATCH 4/9] fix SSR --- src/react/hooks/utils/useBaseQuery.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index a73450fb06f..bbd73cf79d5 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -31,8 +31,9 @@ export function useBaseQuery( ) { const context = useContext(getApolloContext()); const mounted = useMounted(); - const [tick, forceUpdateUnsafe] = useReducer(x => x + 1, 0); - const forceUpdate = () => mounted.current ? forceUpdateUnsafe() : undefined; + const [tick, forceUpdate] = useReducer(x => x + 1, 0); + // This function checks if the component is mounting before force updating. + const forceUpdateClient = () => mounted.current ? forceUpdate() : undefined; const updatedOptions = options ? { ...options, query } : { query }; const queryDataRef = useRef>(); @@ -47,7 +48,7 @@ export function useBaseQuery( // 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); + Promise.resolve().then(forceUpdateClient); } else { // If we're rendering on the server side we can force an update at // any point. From 62497d35998286910f3eae8251523a9bcf64738b Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Thu, 4 Feb 2021 14:17:40 -0500 Subject: [PATCH 5/9] better comment --- src/react/hooks/utils/useBaseQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index bbd73cf79d5..4bc7eabfa44 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -32,7 +32,7 @@ export function useBaseQuery( const context = useContext(getApolloContext()); const mounted = useMounted(); const [tick, forceUpdate] = useReducer(x => x + 1, 0); - // This function checks if the component is mounting before force updating. + // Use on client to check mounting before force updating. const forceUpdateClient = () => mounted.current ? forceUpdate() : undefined; const updatedOptions = options ? { ...options, query } : { query }; From cbdef64225ba604da391a703a3fb2fbfa81f39ff Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Tue, 9 Feb 2021 11:56:17 -0500 Subject: [PATCH 6/9] Check for queryDataRef.current before forcing an update --- src/react/hooks/utils/useBaseQuery.ts | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index 4bc7eabfa44..84abff3b56e 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -1,4 +1,4 @@ -import { useContext, useEffect, useReducer, useRef, RefObject } from 'react'; +import { useContext, useEffect, useReducer, useRef } from 'react'; import { DocumentNode } from 'graphql'; import { TypedDocumentNode } from '@graphql-typed-document-node/core'; @@ -13,42 +13,29 @@ import { useDeepMemo } from './useDeepMemo'; import { OperationVariables } from '../../../core'; import { getApolloContext } from '../../context'; -const useMounted = (): RefObject => { - const mounted = useRef(false); - useEffect(() => { - mounted.current = true; - return () => { - mounted.current = false; - } - }, []); - return mounted; -} - export function useBaseQuery( query: DocumentNode | TypedDocumentNode, options?: QueryHookOptions, lazy = false ) { + const queryDataRef = useRef>(); const context = useContext(getApolloContext()); - const mounted = useMounted(); const [tick, forceUpdate] = useReducer(x => x + 1, 0); - // Use on client to check mounting before force updating. - const forceUpdateClient = () => mounted.current ? forceUpdate() : undefined; + const updatedOptions = options ? { ...options, query } : { query }; - const queryDataRef = useRef>(); const queryData = queryDataRef.current || new QueryData({ options: updatedOptions as QueryDataOptions, context, onNewData() { - if (!queryData.ssrInitiated()) { + if (!queryData.ssrInitiated() && queryDataRef.current) { // 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(forceUpdateClient); + Promise.resolve().then(forceUpdate); } else { // If we're rendering on the server side we can force an update at // any point. From 88c990c0e5a4eacdfc29b488318531cb4cb37869 Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Tue, 9 Feb 2021 12:33:45 -0500 Subject: [PATCH 7/9] Put that ref back where it belongs --- src/react/hooks/utils/useBaseQuery.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index 84abff3b56e..30823c25698 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -18,12 +18,11 @@ export function useBaseQuery( options?: QueryHookOptions, lazy = false ) { - const queryDataRef = useRef>(); const context = useContext(getApolloContext()); const [tick, forceUpdate] = useReducer(x => x + 1, 0); - const updatedOptions = options ? { ...options, query } : { query }; + const queryDataRef = useRef>(); const queryData = queryDataRef.current || new QueryData({ From 94642f64f5ce37dbaf183831763bfb80b83c6535 Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Tue, 9 Feb 2021 13:12:02 -0500 Subject: [PATCH 8/9] Update CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58916789f74..6a4f0728082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ### Improvements +- Avoid calling `forceUpate` when component is unmounted.
+ [@DylanVann](https://github.com/DylanVann) in [#7655](https://github.com/apollographql/apollo-client/pull/7655) + - The `codemods/` top-level directory has been moved into the `scripts/` directory.
[@benjamn](https://github.com/benjamn) in [#7675](https://github.com/apollographql/apollo-client/pull/7675) From 368367312882607e79ddf5bb5eeb5c4e69dac25d Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Tue, 9 Feb 2021 13:13:56 -0500 Subject: [PATCH 9/9] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a4f0728082..df4db286c5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Improvements -- Avoid calling `forceUpate` when component is unmounted.
+- Avoid calling `forceUpdate` when component is unmounted.
[@DylanVann](https://github.com/DylanVann) in [#7655](https://github.com/apollographql/apollo-client/pull/7655) - The `codemods/` top-level directory has been moved into the `scripts/` directory.