Skip to content

Commit

Permalink
fix: delay revalidation if a key is already active and has error (#2338)
Browse files Browse the repository at this point in the history
* fix: delay revalidation if a key is already active and has error

close #2336

* apply code review

* test: add test case for isValidating
  • Loading branch information
promer94 committed Jan 24, 2023
1 parent 1726bc6 commit b30d808
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
7 changes: 7 additions & 0 deletions core/use-swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ export const useSWRHandler = <Data = any, Error = any>(
)

const isInitialMount = !initialMountedRef.current

const hasRevalidator =
EVENT_REVALIDATORS[key] && EVENT_REVALIDATORS[key].length > 0

const cachedData = cached.data

const data = isUndefined(cachedData) ? fallback : cachedData
Expand All @@ -201,6 +205,9 @@ export const useSWRHandler = <Data = any, Error = any>(
// - Not suspense mode and there is no fallback data and `revalidateIfStale` is enabled.
// - `revalidateIfStale` is enabled but `data` is not defined.
const shouldDoInitialRevalidation = (() => {
// if a key already has revalidators and also has error, we should not trigger revalidation
if (hasRevalidator && !isUndefined(error)) return false

// If `revalidateOnMount` is set, we take the value directly.
if (isInitialMount && !isUndefined(revalidateOnMount))
return revalidateOnMount
Expand Down
56 changes: 56 additions & 0 deletions test/use-swr-error.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,60 @@ describe('useSWR - error', () => {
// Since there's only 1 request fired, only 1 error event should be reported.
expect(errorEvents.length).toBe(1)
})

it('should not should not trigger revalidation when a key is already active and has error - isLoading', async () => {
const key = createKey()
const useData = () => {
return useSWR<any, any>(
key,
() => createResponse(new Error('error!'), { delay: 200 }),
undefined
)
}
const Page = () => {
useData()
return null
}
const App = () => {
const { error, isLoading } = useData()
if (isLoading) return <span>loading</span>
return (
<div>
{error ? error.message : ''},{isLoading.toString()}
<Page />
</div>
)
}
renderWithConfig(<App />)
screen.getByText('loading')
await screen.findByText('error!,false')
})

it('should not should not trigger revalidation when a key is already active and has error - isValidating', async () => {
const key = createKey()
const useData = () => {
return useSWR<any, any>(
key,
() => createResponse(new Error('error!'), { delay: 200 }),
undefined
)
}
const Page = () => {
useData()
return null
}
const App = () => {
const { error, isValidating } = useData()
if (isValidating) return <span>validating</span>
return (
<div>
{error ? error.message : ''},{isValidating.toString()}
<Page />
</div>
)
}
renderWithConfig(<App />)
screen.getByText('validating')
await screen.findByText('error!,false')
})
})
6 changes: 3 additions & 3 deletions test/use-swr-loading.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ describe('useSWR - loading', () => {
await sleep(50)
throw new Error(key)
},
dedupingInterval: 0
dedupingInterval: 0,
errorRetryInterval: 50
})

return isValidating ? <>validating</> : <>stopped</>
Expand All @@ -251,8 +252,7 @@ describe('useSWR - loading', () => {
screen.getByText('stopped,')

fireEvent.click(screen.getByText('start'))
await executeWithoutBatching(() => sleep(20))
screen.getByText('validating,validating')
await screen.findByText('validating,validating')

// Pause before it resolves
paused = true
Expand Down

0 comments on commit b30d808

Please sign in to comment.