Skip to content

Commit

Permalink
Fix #182 (#207)
Browse files Browse the repository at this point in the history
* Fix #182

* use only 2 useEffect
  • Loading branch information
promer94 authored and shuding committed Dec 23, 2019
1 parent 5b96586 commit 915b008
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 26 deletions.
58 changes: 32 additions & 26 deletions src/use-swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,27 +454,6 @@ function useSWR<Data = any, Error = any>(
CACHE_REVALIDATORS[key].push(onUpdate)
}

// set up polling
let timeout = null
if (config.refreshInterval) {
const tick = async () => {
if (
!errorRef.current &&
(config.refreshWhenHidden || isDocumentVisible()) &&
(!config.refreshWhenOffline && isOnline())
) {
// only revalidate when the page is visible
// if API request errored, we stop polling in this round
// and let the error retry function handle it
await softRevalidate()
}

const interval = config.refreshInterval
timeout = setTimeout(tick, interval)
}
timeout = setTimeout(tick, config.refreshInterval)
}

// set up reconnecting when the browser regains network connection
let reconnect = null
if (config.revalidateOnReconnect) {
Expand Down Expand Up @@ -507,15 +486,42 @@ function useSWR<Data = any, Error = any>(
}
}

if (timeout !== null) {
clearTimeout(timeout)
}

if (reconnect !== null) {
removeEventListener('online', reconnect)
}
}
}, [key, config.refreshInterval, revalidate])
}, [key, revalidate])

// set up polling
useIsomorphicLayoutEffect(() => {
let timer = null
const tick = async () => {
if (
!errorRef.current &&
(config.refreshWhenHidden || isDocumentVisible()) &&
(!config.refreshWhenOffline && isOnline())
) {
// only revalidate when the page is visible
// if API request errored, we stop polling in this round
// and let the error retry function handle it
await revalidate({ dedupe: true })
}
if (config.refreshInterval) {
timer = setTimeout(tick, config.refreshInterval)
}
}
if (config.refreshInterval) {
timer = setTimeout(tick, config.refreshInterval)
}
return () => {
if (timer) clearTimeout(timer)
}
}, [
config.refreshInterval,
config.refreshWhenHidden,
config.refreshWhenOffline,
revalidate
])

// suspense
if (config.suspense) {
Expand Down
54 changes: 54 additions & 0 deletions test/use-swr.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,60 @@ describe('useSWR - refresh', () => {
await act(() => new Promise(res => setTimeout(res, 200))) // update
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 2"`)
})

it('should update data upon interval changes', async () => {
let count = 0
function Page() {
const [int, setInt] = React.useState(200)
const { data } = useSWR('/api', () => count++, {
refreshInterval: int,
dedupingInterval: 100
})
return <div onClick={() => setInt(int + 100)}>count: {data}</div>
}
const { container } = render(<Page />)
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: "`)

await waitForDomChange({ container }) // mount
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 0"`)
await act(() => {
return new Promise(res => setTimeout(res, 210))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 1"`)
await act(() => {
return new Promise(res => setTimeout(res, 50))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 1"`)
await act(() => {
return new Promise(res => setTimeout(res, 150))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 2"`)
await act(() => {
fireEvent.click(container.firstElementChild)
// it will clear 200ms timer and setup a new 300ms timer
return new Promise(res => setTimeout(res, 200))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 2"`)
await act(() => {
return new Promise(res => setTimeout(res, 110))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 3"`)
await act(() => {
// wait for new 300ms timer
return new Promise(res => setTimeout(res, 310))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 4"`)
await act(() => {
fireEvent.click(container.firstElementChild)
// it will clear 300ms timer and setup a new 400ms timer
return new Promise(res => setTimeout(res, 300))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 4"`)
await act(() => {
return new Promise(res => setTimeout(res, 110))
})
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"count: 5"`)
})
})

describe('useSWR - revalidate', () => {
Expand Down

0 comments on commit 915b008

Please sign in to comment.