Skip to content

Commit

Permalink
fix: do unsubscribe synchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
promer94 committed Jun 2, 2023
1 parent a7eea72 commit d0c7a3a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
23 changes: 10 additions & 13 deletions subscription/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,16 @@ export const subscription = (<Data = any, Error = any>(useSWRNext: SWRHook) =>
}

return () => {
// Prevent frequent unsubscribe caused by unmount
setTimeout(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const count = subscriptions.get(subscriptionKey)! - 1

subscriptions.set(subscriptionKey, count)

// Dispose if it's the last one.
if (!count) {
const dispose = disposers.get(subscriptionKey)
dispose?.()
}
})
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const count = subscriptions.get(subscriptionKey)! - 1

subscriptions.set(subscriptionKey, count)

// Dispose if it's the last one.
if (!count) {
const dispose = disposers.get(subscriptionKey)
dispose?.()
}
}

// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
54 changes: 53 additions & 1 deletion test/use-swr-subscription.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { act, screen } from '@testing-library/react'
import { act, fireEvent, screen } from '@testing-library/react'
import { sleep, renderWithConfig, createKey } from './utils'
import useSWRSubscription from 'swr/subscription'
import useSWR from 'swr'
import { useEffect, useState } from 'react'

describe('useSWRSubscription', () => {
it('should update the state', async () => {
Expand Down Expand Up @@ -206,4 +207,55 @@ describe('useSWRSubscription', () => {
await act(() => sleep(100))
screen.getByText(`swr:${swrKey}2`)
})

it('should support singleton subscription', async () => {
const placeholderFn: (data: number) => void = () => {}
let callback: (data: number) => void = placeholderFn
const sub = (fn: (data: number) => void) => {
console.log('sub')
callback = fn
return () => {
console.log('unsub')
callback = placeholderFn
}
}
const emit = (data: number) => {
callback(data)
}
const useSubData = (key: number) =>
useSWRSubscription(key.toString(), (_, { next }) =>
sub(data => next(null, data + key))
)
const App = () => {
const [key, setKey] = useState(0)
const { data } = useSubData(key)
useEffect(() => {
callback(1)
}, [])
return (
<div className="App">
<p>key: {key}</p>
<p className="read-the-docs">data: {data}</p>
<button
onClick={() => {
setKey(value => value + 1)
setTimeout(() => {
emit(2)
console.log(callback === placeholderFn)
}, 100)
}}
>
add
</button>
</div>
)
}
renderWithConfig(<App />)
await screen.findByText(`key: 0`)
await screen.findByText(`data: 1`)
fireEvent.click(screen.getByText('add'))
await act(() => sleep(100))
await screen.findByText(`key: 1`)
await screen.findByText(`data: 3`)
})
})

0 comments on commit d0c7a3a

Please sign in to comment.