Skip to content

Commit

Permalink
feature: provide config.isIdle indicating idle state and stop revalid…
Browse files Browse the repository at this point in the history
…ation (#845)

* feature: ignore revalidations when config.isIdle() is truthy

* add test

* rename to isPaused(), ignore errors in catch
  • Loading branch information
huozhi authored Dec 31, 2020
1 parent 2248899 commit 00c5847
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ const defaultConfig: ConfigInterface = {

fetcher: webPreset.fetcher,
isOnline: webPreset.isOnline,
isDocumentVisible: webPreset.isDocumentVisible
isDocumentVisible: webPreset.isDocumentVisible,
isPaused: () => false
}

export { cache }
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface ConfigInterface<

isOnline?: () => boolean
isDocumentVisible?: () => boolean
isPaused?: () => boolean
onLoadingSlow?: (key: string, config: ConfigInterface<Data, Error>) => void
onSuccess?: (
data: Data,
Expand Down
8 changes: 8 additions & 0 deletions src/use-swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ function useSWR<Data = any, Error = any>(
): Promise<boolean> => {
if (!key || !fn) return false
if (unmountedRef.current) return false
if (config.isPaused()) return false
revalidateOpts = Object.assign({ dedupe: false }, revalidateOpts)

let loading = true
Expand Down Expand Up @@ -499,6 +500,13 @@ function useSWR<Data = any, Error = any>(
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
Expand Down
46 changes: 44 additions & 2 deletions test/use-swr.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1875,15 +1875,15 @@ describe('useSWR - local mutation', () => {
})
})

describe('useSWR - context configs', () => {
describe('useSWR - configs', () => {
afterEach(cleanup)

it('should read the config fallback from the context', async () => {
let value = 0
const fetcher = () => value++

function Section() {
const { data } = useSWR('dynamic-10')
const { data } = useSWR('config-0')
return <div>data: {data}</div>
}
function Page() {
Expand All @@ -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 <div onClick={() => boundMutate()}>data: {data}</div>
}
const { container } = render(<Page />)

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', () => {
Expand Down

0 comments on commit 00c5847

Please sign in to comment.