Skip to content

Commit

Permalink
fix: revalidate with initialData when changing the key (#961)
Browse files Browse the repository at this point in the history
* fix: revalidate with initialData when changing the key

* test: add the return data when a request is in flight

* test: return initialData while revalidating
  • Loading branch information
koba04 authored Mar 9, 2021
1 parent 43b2920 commit 3f7e579
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
12 changes: 8 additions & 4 deletions src/use-swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,9 @@ function useSWR<Data = any, Error = any>(
? 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]
Expand Down Expand Up @@ -558,6 +558,7 @@ function useSWR<Data = any, Error = any>(
// 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),
Expand All @@ -579,7 +580,10 @@ function useSWR<Data = any, Error = any>(
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
Expand Down
48 changes: 46 additions & 2 deletions test/use-swr-integration.test.tsx
Original file line number Diff line number Diff line change
@@ -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'

Expand Down Expand Up @@ -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 (
<div onClick={() => setKey('initial-data-with-initial-data-update')}>
{data ? `hello, ${data}` : 'loading'}
</div>
)
}

const { container } = render(<Page />)

// 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')

Expand Down

0 comments on commit 3f7e579

Please sign in to comment.