diff --git a/src/use-swr.ts b/src/use-swr.ts index 637bac3d5..794e96285 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -232,9 +232,9 @@ function useSWR( ? args[1] : args.length === 2 && typeof args[1] === 'function' ? args[1] - : /** - pass fn as null will disable revalidate - https://paco.sh/blog/shared-hook-state-with-swr + : /** + pass fn as null will disable revalidate + https://paco.sh/blog/shared-hook-state-with-swr */ args[1] === null ? args[1] @@ -558,6 +558,7 @@ function useSWR( // after `key` updates, we need to mark it as mounted unmountedRef.current = false + const isUpdating = initialMountedRef.current initialMountedRef.current = true // after the component is mounted (hydrated), @@ -579,7 +580,10 @@ function useSWR( const softRevalidate = () => revalidate({ dedupe: true }) // trigger a revalidation - if (willRevalidateOnMount()) { + if ( + isUpdating || + willRevalidateOnMount() + ) { if (typeof latestKeyedData !== 'undefined' && !IS_SERVER) { // delay revalidate if there's cache // to not block the rendering diff --git a/test/use-swr-integration.test.tsx b/test/use-swr-integration.test.tsx index f6cd292b2..5f268fc95 100644 --- a/test/use-swr-integration.test.tsx +++ b/test/use-swr-integration.test.tsx @@ -1,5 +1,5 @@ -import { act, render, screen } from '@testing-library/react' -import React, { useEffect } from 'react' +import { act, render, screen, fireEvent } from '@testing-library/react' +import React, { useState, useEffect } from 'react' import useSWR from '../src' import { sleep } from './utils' @@ -311,6 +311,50 @@ describe('useSWR', () => { ) }) + it('should revalidate even if initialData is provided', async () => { + const fetcher = async key => { + await sleep(50) + return key + } + + function Page() { + const [key, setKey] = useState('initial-data-with-initial-data') + const { data } = useSWR(key, fetcher, { + initialData: 'Initial' + }) + return ( +
setKey('initial-data-with-initial-data-update')}> + {data ? `hello, ${data}` : 'loading'} +
+ ) + } + + const { container } = render() + + // render with the initial data + await screen.findByText('hello, Initial') + + await act(() => sleep(1)) + fireEvent.focus(window) + + await screen.findByText('hello, initial-data-with-initial-data') + + // change the key + await act(() => sleep(1)) + fireEvent.click(container.firstElementChild) + + // a request is still in flight + await act(() => sleep(10)) + // while validating, SWR returns the initialData + // https://github.com/vercel/swr/pull/961/files#r588928241 + expect(container.firstChild.textContent).toMatchInlineSnapshot( + `"hello, Initial"` + ) + + // render with data the fetcher returns + await screen.findByText('hello, initial-data-with-initial-data-update') + }) + it('should set config as second parameter', async () => { const fetcher = jest.fn(() => 'SWR')