diff --git a/.changeset/broadcast-added-keeps-error.md b/.changeset/broadcast-added-keeps-error.md new file mode 100644 index 00000000000..b6ae270deda --- /dev/null +++ b/.changeset/broadcast-added-keeps-error.md @@ -0,0 +1,5 @@ +--- +'@tanstack/query-broadcast-client-experimental': patch +--- + +fix: don't overwrite a query that has no data, such as one in error, when another tab broadcasts an `added` event for a query that has not settled yet diff --git a/packages/query-broadcast-client-experimental/src/__tests__/index.test.ts b/packages/query-broadcast-client-experimental/src/__tests__/index.test.ts index c756fc6f2ed..b09cd7fe640 100644 --- a/packages/query-broadcast-client-experimental/src/__tests__/index.test.ts +++ b/packages/query-broadcast-client-experimental/src/__tests__/index.test.ts @@ -175,6 +175,71 @@ describe('broadcastQueryClient', () => { value: 'from other tab', }) }) + + it('should not overwrite an existing query in error when an "added" message with a fresh state arrives for it', async () => { + const existingKey = queryKey() + const error = new Error('down') + + broadcastQueryClient({ + queryClient, + broadcastChannel: 'test_channel', + }) + + await queryClient + .query({ + queryKey: existingKey, + queryFn: () => Promise.reject(error), + retry: false, + }) + .catch(() => undefined) + const existingQuery = queryCache.find({ queryKey: existingKey })! + + lastCreatedChannel.onmessage?.({ + type: 'added', + queryHash: existingQuery.queryHash, + queryKey: existingKey, + state: { + status: 'pending', + fetchStatus: 'idle', + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + }, + }) + expect(queryClient.getQueryState(existingKey)?.status).toBe('error') + expect(queryClient.getQueryState(existingKey)?.error).toBe(error) + }) + + it('should adopt an "added" message\'s error state for an existing query that has no data yet', () => { + const existingKey = queryKey() + const error = new Error('down') + + broadcastQueryClient({ + queryClient, + broadcastChannel: 'test_channel', + }) + + const existingQuery = queryCache.build(queryClient, { + queryKey: existingKey, + }) + + lastCreatedChannel.onmessage?.({ + type: 'added', + queryHash: existingQuery.queryHash, + queryKey: existingKey, + state: { + status: 'error', + fetchStatus: 'idle', + data: undefined, + dataUpdatedAt: 0, + error, + errorUpdatedAt: 0, + }, + }) + expect(queryClient.getQueryState(existingKey)?.status).toBe('error') + expect(queryClient.getQueryState(existingKey)?.error).toBe(error) + }) }) describe('postMessage error handling', () => { diff --git a/packages/query-broadcast-client-experimental/src/index.ts b/packages/query-broadcast-client-experimental/src/index.ts index c292b72353b..0c405d7fdfe 100644 --- a/packages/query-broadcast-client-experimental/src/index.ts +++ b/packages/query-broadcast-client-experimental/src/index.ts @@ -192,7 +192,7 @@ export function broadcastQueryClient({ } } else if (type === 'added') { if (query) { - if (query.state.data === undefined) { + if (query.state.data === undefined && state.status !== 'pending') { query.setState(state) } return