From 00c5847ce6e95902920933aa1d49c7143f8ce4ba Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 1 Jan 2021 03:38:17 +0800 Subject: [PATCH] feature: provide config.isIdle indicating idle state and stop revalidation (#845) * feature: ignore revalidations when config.isIdle() is truthy * add test * rename to isPaused(), ignore errors in catch --- src/config.ts | 3 ++- src/types.ts | 1 + src/use-swr.ts | 8 ++++++++ test/use-swr.test.tsx | 46 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index df9ff3b58..c193b7e9a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -70,7 +70,8 @@ const defaultConfig: ConfigInterface = { fetcher: webPreset.fetcher, isOnline: webPreset.isOnline, - isDocumentVisible: webPreset.isDocumentVisible + isDocumentVisible: webPreset.isDocumentVisible, + isPaused: () => false } export { cache } diff --git a/src/types.ts b/src/types.ts index 2c75713e1..e28747633 100644 --- a/src/types.ts +++ b/src/types.ts @@ -22,6 +22,7 @@ export interface ConfigInterface< isOnline?: () => boolean isDocumentVisible?: () => boolean + isPaused?: () => boolean onLoadingSlow?: (key: string, config: ConfigInterface) => void onSuccess?: ( data: Data, diff --git a/src/use-swr.ts b/src/use-swr.ts index ce4ff6bfd..3aa74511b 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -376,6 +376,7 @@ function useSWR( ): Promise => { if (!key || !fn) return false if (unmountedRef.current) return false + if (config.isPaused()) return false revalidateOpts = Object.assign({ dedupe: false }, revalidateOpts) let loading = true @@ -499,6 +500,13 @@ function useSWR( delete CONCURRENT_PROMISES[key] delete CONCURRENT_PROMISES_TS[key] + if (config.isPaused()) { + dispatch({ + isValidating: false + }) + return false + } + cache.set(keyErr, err) // get a new error diff --git a/test/use-swr.test.tsx b/test/use-swr.test.tsx index 0640ad9a4..e18d3d820 100644 --- a/test/use-swr.test.tsx +++ b/test/use-swr.test.tsx @@ -1875,7 +1875,7 @@ describe('useSWR - local mutation', () => { }) }) -describe('useSWR - context configs', () => { +describe('useSWR - configs', () => { afterEach(cleanup) it('should read the config fallback from the context', async () => { @@ -1883,7 +1883,7 @@ describe('useSWR - context configs', () => { const fetcher = () => value++ function Section() { - const { data } = useSWR('dynamic-10') + const { data } = useSWR('config-0') return
data: {data}
} function Page() { @@ -1905,6 +1905,48 @@ describe('useSWR - context configs', () => { await act(() => new Promise(res => setTimeout(res, 110))) // update expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 1"`) }) + + it('should stop revalidations when config.isPaused returns true', async () => { + const key = 'config-1' + let value = 0 + let isSwrPaused = false + const fetcher = () => { + if (value === 2) throw new Error() + return value++ + } + + function Page() { + // config provider + const { mutate: boundMutate, data } = useSWR(key, fetcher, { + revalidateOnMount: true, + isPaused() { + return isSwrPaused + } + }) + + useEffect(() => { + // revalidate on mount and turn to idle + isSwrPaused = true + }, []) + + return
boundMutate()}>data: {data}
+ } + const { container } = render() + + await waitForDomChange({ container }) + expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`) + await act(async () => await 0) + expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`) + fireEvent.click(container.firstElementChild) + await act(async () => await 0) + expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`) + isSwrPaused = true + fireEvent.click(container.firstElementChild) + isSwrPaused = false + await act(async () => await 0) + // await act(() => {return new Promise(res => setTimeout(res, 50))}) + expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`) + }) }) describe('useSWR - suspense', () => {