Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
shuding authored and nevilm-lt committed Apr 22, 2022
1 parent 95889a3 commit 9bed06c
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 16 deletions.
31 changes: 22 additions & 9 deletions src/utils/cache.ts
Expand Up @@ -41,9 +41,10 @@ export const initCache = <Data = any>(
// If there's no global state bound to the provider, create a new one with the
// new mutate function.
const EVENT_REVALIDATORS = {}
const mutate = internalMutate.bind(UNDEFINED, provider) as ScopedMutator<
Data
>
const mutate = internalMutate.bind(
UNDEFINED,
provider
) as ScopedMutator<Data>
let unmount = noop

// Update the state if it's new, or the provider has been extended.
Expand All @@ -60,18 +61,30 @@ export const initCache = <Data = any>(
// This is a new provider, we need to initialize it and setup DOM events
// listeners for `focus` and `reconnect` actions.
if (!IS_SERVER) {
// When listening to the native events for auto revalidations,
// we intentionally put a delay (setTimeout) here to make sure they are
// fired after immediate JavaScript executions, which can possibly be
// React's state updates.
// This avoids some unnecessary revalidations such as
// https://github.com/vercel/swr/issues/1680.
const releaseFocus = opts.initFocus(
revalidateAllKeys.bind(
setTimeout.bind(
UNDEFINED,
EVENT_REVALIDATORS,
revalidateEvents.FOCUS_EVENT
revalidateAllKeys.bind(
UNDEFINED,
EVENT_REVALIDATORS,
revalidateEvents.FOCUS_EVENT
)
)
)
const releaseReconnect = opts.initReconnect(
revalidateAllKeys.bind(
setTimeout.bind(
UNDEFINED,
EVENT_REVALIDATORS,
revalidateEvents.RECONNECT_EVENT
revalidateAllKeys.bind(
UNDEFINED,
EVENT_REVALIDATORS,
revalidateEvents.RECONNECT_EVENT
)
)
)
unmount = () => {
Expand Down
14 changes: 7 additions & 7 deletions src/utils/web-preset.ts
Expand Up @@ -36,21 +36,21 @@ const isVisible = () => {
return true
}

const initFocus = (cb: () => void) => {
const initFocus = (callback: () => void) => {
// focus revalidate
onDocumentEvent('visibilitychange', cb)
onWindowEvent('focus', cb)
onDocumentEvent('visibilitychange', callback)
onWindowEvent('focus', callback)
return () => {
offDocumentEvent('visibilitychange', cb)
offWindowEvent('focus', cb)
offDocumentEvent('visibilitychange', callback)
offWindowEvent('focus', callback)
}
}

const initReconnect = (cb: () => void) => {
const initReconnect = (callback: () => void) => {
// revalidate on reconnected
const onOnline = () => {
online = true
cb()
callback()
}
// nothing to revalidate, just update the status
const onOffline = () => {
Expand Down
2 changes: 2 additions & 0 deletions test/use-swr-cache.test.tsx
Expand Up @@ -183,6 +183,7 @@ describe('useSWR - cache provider', () => {
await screen.findByText('0')
await nextTick()
await focusOn(window)
await nextTick()
screen.getByText('1')
})

Expand Down Expand Up @@ -396,6 +397,7 @@ describe('useSWR - global cache', () => {
await screen.findByText('0')
await nextTick()
await focusOn(window)
await nextTick()
screen.getByText('1')
})

Expand Down
25 changes: 25 additions & 0 deletions test/use-swr-focus.test.tsx
Expand Up @@ -220,4 +220,29 @@ describe('useSWR - focus', () => {
await focusWindow()
await screen.findByText('data: 1')
})

it('should not revalidate on focus when key changes in the same tick', async () => {
const fetchLogs = []

function Page() {
const [key, setKey] = useState(() => createKey())
useSWR(key, k => fetchLogs.push(k), {
revalidateOnFocus: true,
dedupingInterval: 0
})
return <div onClick={() => setKey(createKey())}>change key</div>
}

renderWithConfig(<Page />)
await waitForNextTick()

fireEvent.focus(window)
fireEvent.click(screen.getByText('change key'))

await waitForNextTick()

// Only fetched twice with the initial and the new keys.
expect(fetchLogs.length).toBe(2)
expect(fetchLogs[0]).not.toEqual(fetchLogs[1])
})
})

0 comments on commit 9bed06c

Please sign in to comment.