From 601fe3e34d9537f660043daec343d9dabff2c9b2 Mon Sep 17 00:00:00 2001 From: huozhi Date: Thu, 7 May 2020 11:23:02 +0800 Subject: [PATCH] throw promise when key is falsy in suspense --- src/use-swr.ts | 13 +++++++---- test/use-swr.test.tsx | 53 +++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/use-swr.ts b/src/use-swr.ts index c744a5ecf..fd57d4a10 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -372,7 +372,7 @@ function useSWR( // update the state if the key changed (not the inital render) or cache updated if ( - (keyRef.current !== key && (!keyRef.current && !key)) || + keyRef.current !== key || !config.compare(currentHookData, latestKeyedData) ) { dispatch({ data: latestKeyedData }) @@ -543,10 +543,15 @@ function useSWR( typeof latestError === 'undefined' ) { // need to start the request if it hasn't + if (!CONCURRENT_PROMISES[key]) { - // trigger revalidate immediately - // to get the promise - revalidate() + if (key) { + // trigger revalidate immediately + // to get the promise + revalidate() + } else { + throw Promise.reject() + } } if ( diff --git a/test/use-swr.test.tsx b/test/use-swr.test.tsx index cc09825af..e7e28ef01 100644 --- a/test/use-swr.test.tsx +++ b/test/use-swr.test.tsx @@ -1270,36 +1270,49 @@ describe('useSWR - suspense', () => { // hold render when suspense it('should pause when key is falsy', async () => { - const renderedResults = [] - - function Section() { - const [key, setKey] = useState(null) + function SectionContent({ swrKey, onClick }) { const { data } = useSWR( - key, - k => new Promise(res => setTimeout(() => res(k), 50)), + () => (swrKey % 2 === 0 ? null : swrKey), + k => new Promise(res => setTimeout(() => res(k), 30)), { suspense: true } ) - useEffect(() => { - setKey('suspense-9') - }, []) + return ( +
+ {swrKey && data ? 'suspense-' + (9 + Number(data)) : undefined} +
+ ) + } - if (data !== renderedResults[renderedResults.length - 1]) { - renderedResults.push(data) - } + const Section = () => { + const [key, setKey] = useState(0) + const handleClick = () => setKey(key + 1) - return
{data}
+ return ( + fallback}> + + + ) } - render( - fallback}> -
- - ) - await act(() => new Promise(res => setTimeout(res, 210))) - expect(renderedResults).toEqual(['suspense-9']) + const { container } = render(
) + + async function clickAndWait(duration) { + fireEvent.click(container.firstElementChild) + return await act( + () => new Promise(resolve => setTimeout(resolve, duration)) + ) + } + + expect(container.textContent).toMatchInlineSnapshot(`"fallback"`) + await clickAndWait(100) + expect(container.textContent).toMatchInlineSnapshot(`"suspense-10"`) + await clickAndWait(100) + expect(container.textContent).toMatchInlineSnapshot(`"fallback"`) + await clickAndWait(100) + expect(container.textContent).toMatchInlineSnapshot(`"suspense-10"`) }) })