Skip to content

broadcastClient: removing query from one tab removes it from all tabs, even if others still have observers #7487

@c-ehrlich

Description

@c-ehrlich

Describe the bug

When using broadcastQueryClient:

  • Unmounting a query (with the last observer being removed) in one tab also removes that query in the other tab after gcTime hits
  • After re-mounting the query, it is still not observed by the other tab, and invalidation works in neither direction

Your minimal, reproducible example

(no stackblitz as their containerization seems to break broadcast channels, but see "Steps to reproduce" for a repo, also I've recorded a video demo)

Steps to reproduce

Sample repo: https://github.com/c-ehrlich/broadcast-invalidation-demo

To see the bug

  • cd before, pnpm i, pnpm dev
  • open the application in two windows, show devtools
  • invalidating across windows should work
  • click "hide" in one window, wait for gcTime - the query is now no longer observed in both windows, and invalidation is broken
  • click "show" to get the query back - invalidation will still be broken in both directions

To see a demo of my rough fix

Expected behavior

  • Unmounting a query (with the last observer being removed) in one tab should not remove that query in the other tab
  • Invalidation should work across tabs even when a query is not being observed in the tab that invalidates it

(not sure what the intended behaviour is, but these would be my expectations for the broadcastClient)

How often does this bug happen?

Every time

Screenshots or Videos

https://www.loom.com/share/e7da8b5d3cdb4b36a3fbf076d7ccb6b8

(the data updates twice shortly after each other at 1:16 because i had a third tab open, see "Additional context")

Platform

Chrome 124.0.6367.208 on MacOS 14.3 (also confirmed in Firefox on Windows 11)

Tanstack Query adapter

react-query

TanStack Query version

5.39.0

TypeScript version

5.2.2

Additional context

My implementation still has one significant inefficiency:

  • open three tabs instead of two
  • hide the query in one of them, and invalidate there. now both of the other windows will refetch
  • ideally, only one refetch would be necessary. i could imagine achieving this through either "borrowing" the query from an instance that has it, or by keeping track of invalidation across instances and making only one of them refetch

Other considerations:

  • @TkDodo mentioned in this discussion that "the broadcastQueryClient plugin just assumes the same queryClients in all tabs". Not quite sure what this means. If it were possible to share an actual QueryClient, would it not become unnecessary to pass messages between tabs? But if that is somehow possible, it would be a much better solution.
  • I would be open to work on this if you agree on the intended behaviour

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions