Skip to content

Commit 674f83e

Browse files
gopnik5TkDodo
andauthored
fix: (query-broadcast-client-experimental) - removing query from one tab doesn't remove it from all tabs (#9017)
* fix(solid-query): client() doesn't return undefined * fix: (query-broadcast-client-experimental) - removing query from one tab doesn't remove it from all tabs * fix: (query-broadcast-client-experimental) - removing query from one tab doesn't remove it from all tabs * isolated tests * chore: add test config --------- Co-authored-by: Dominik Dorfmeister <[email protected]>
1 parent 18af643 commit 674f83e

File tree

6 files changed

+118
-10
lines changed

6 files changed

+118
-10
lines changed

packages/query-broadcast-client-experimental/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
"test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build",
2929
"test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build",
3030
"test:types:tscurrent": "tsc --build",
31+
"test:lib": "vitest",
32+
"test:lib:dev": "pnpm run test:lib --watch",
3133
"test:build": "publint --strict && attw --pack",
3234
"build": "tsup --tsconfig tsconfig.prod.json"
3335
},
@@ -60,6 +62,8 @@
6062
"broadcast-channel": "^7.0.0"
6163
},
6264
"devDependencies": {
65+
"@testing-library/react": "^16.1.0",
66+
"@vitejs/plugin-react": "^4.3.4",
6367
"npm-run-all2": "^5.0.0"
6468
}
6569
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { QueryClient } from '@tanstack/query-core'
2+
import { beforeEach, describe, expect, it } from 'vitest'
3+
import { broadcastQueryClient } from '..'
4+
import type { QueryCache } from '@tanstack/query-core'
5+
6+
describe('broadcastQueryClient', () => {
7+
let queryClient: QueryClient
8+
let queryCache: QueryCache
9+
10+
beforeEach(() => {
11+
queryClient = new QueryClient()
12+
queryCache = queryClient.getQueryCache()
13+
})
14+
15+
it('should subscribe to the query cache', async () => {
16+
broadcastQueryClient({
17+
queryClient,
18+
broadcastChannel: 'test_channel',
19+
})
20+
expect(queryCache.hasListeners()).toBe(true)
21+
})
22+
23+
it('should not have any listeners after cleanup', async () => {
24+
const unsubscribe = broadcastQueryClient({
25+
queryClient,
26+
broadcastChannel: 'test_channel',
27+
})
28+
unsubscribe()
29+
expect(queryCache.hasListeners()).toBe(false)
30+
})
31+
})

packages/query-broadcast-client-experimental/src/index.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function broadcastQueryClient({
1212
queryClient,
1313
broadcastChannel = 'tanstack-query',
1414
options,
15-
}: BroadcastQueryClientOptions) {
15+
}: BroadcastQueryClientOptions): () => void {
1616
let transaction = false
1717
const tx = (cb: () => void) => {
1818
transaction = true
@@ -27,13 +27,13 @@ export function broadcastQueryClient({
2727

2828
const queryCache = queryClient.getQueryCache()
2929

30-
queryClient.getQueryCache().subscribe((queryEvent) => {
30+
const unsubscribe = queryClient.getQueryCache().subscribe((queryEvent) => {
3131
if (transaction) {
3232
return
3333
}
3434

3535
const {
36-
query: { queryHash, queryKey, state },
36+
query: { queryHash, queryKey, state, observers },
3737
} = queryEvent
3838

3939
if (queryEvent.type === 'updated' && queryEvent.action.type === 'success') {
@@ -45,13 +45,21 @@ export function broadcastQueryClient({
4545
})
4646
}
4747

48-
if (queryEvent.type === 'removed') {
48+
if (queryEvent.type === 'removed' && observers.length > 0) {
4949
channel.postMessage({
5050
type: 'removed',
5151
queryHash,
5252
queryKey,
5353
})
5454
}
55+
56+
if (queryEvent.type === 'added') {
57+
channel.postMessage({
58+
type: 'added',
59+
queryHash,
60+
queryKey,
61+
})
62+
}
5563
})
5664

5765
channel.onmessage = (action) => {
@@ -62,9 +70,9 @@ export function broadcastQueryClient({
6270
tx(() => {
6371
const { type, queryHash, queryKey, state } = action
6472

65-
if (type === 'updated') {
66-
const query = queryCache.get(queryHash)
73+
const query = queryCache.get(queryHash)
6774

75+
if (type === 'updated') {
6876
if (query) {
6977
query.setState(state)
7078
return
@@ -79,12 +87,27 @@ export function broadcastQueryClient({
7987
state,
8088
)
8189
} else if (type === 'removed') {
82-
const query = queryCache.get(queryHash)
83-
8490
if (query) {
8591
queryCache.remove(query)
8692
}
93+
} else if (type === 'added') {
94+
if (query) {
95+
query.setState(state)
96+
return
97+
}
98+
queryCache.build(
99+
queryClient,
100+
{
101+
queryKey,
102+
queryHash,
103+
},
104+
state,
105+
)
87106
}
88107
})
89108
}
109+
return () => {
110+
unsubscribe()
111+
channel.close()
112+
}
90113
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import '@testing-library/jest-dom/vitest'
2+
import { act, cleanup as cleanupRTL } from '@testing-library/react'
3+
import { afterEach } from 'vitest'
4+
import { notifyManager } from '@tanstack/query-core'
5+
6+
// https://testing-library.com/docs/react-testing-library/api#cleanup
7+
afterEach(() => {
8+
cleanupRTL()
9+
})
10+
11+
// Wrap notifications with act to make sure React knows about React Query updates
12+
notifyManager.setNotifyFunction((fn) => {
13+
act(fn)
14+
})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { defineConfig } from 'vitest/config'
2+
import react from '@vitejs/plugin-react'
3+
4+
import packageJson from './package.json'
5+
6+
export default defineConfig({
7+
plugins: [react()],
8+
// fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660
9+
resolve: {
10+
conditions: ['@tanstack/custom-condition'],
11+
},
12+
environments: {
13+
ssr: {
14+
resolve: {
15+
conditions: ['@tanstack/custom-condition'],
16+
},
17+
},
18+
},
19+
test: {
20+
name: packageJson.name,
21+
dir: './src',
22+
watch: false,
23+
environment: 'jsdom',
24+
setupFiles: ['test-setup.ts'],
25+
coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] },
26+
typecheck: { enabled: true },
27+
restoreMocks: true,
28+
retry: process.env.CI ? 3 : 0,
29+
},
30+
})

pnpm-lock.yaml

Lines changed: 8 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)