Skip to content

Fix useLiveRxQuery leaking the live query subscription on unmount - #8971

Merged
pubkey merged 2 commits into
pubkey:masterfrom
Steve0x2a:fix/use-live-rx-query-unsubscribe
Aug 19, 2026
Merged

Fix useLiveRxQuery leaking the live query subscription on unmount#8971
pubkey merged 2 commits into
pubkey:masterfrom
Steve0x2a:fix/use-live-rx-query-unsubscribe

Conversation

@Steve0x2a

Copy link
Copy Markdown
Contributor

This PR contains:

A BUGFIX and IMPROVED TESTS.

Reported by chris-rnwbl in #8964.

Fixes #8964.

Describe the problem you have without this PR

useLiveRxQuery / useRxQueryBase subscribed to rxQuery.$ inside an async runQuery callback and returned () => subscription.unsubscribe() from that callback. React useEffect only uses a function returned synchronously as cleanup. The Promise resolved value was ignored, so unmount (and query changes) never unsubscribed.

useRxDocument in the same plugin already returns cleanup from useEffect correctly.

Fix

Drop async from runQuery so the live path can return unsubscribe synchronously. useEffect now return runQuery(). The non-live exec() path uses .then() / rejection handler instead of await.

This does not change the useRxDocument first-paint loading behavior from #8965.

Test case

should unsubscribe from the live query when the hook is unmounted in test/react/react-hooks.test.tsx:

  1. mount useLiveRxQuery
  2. wait until the query settles
  3. assert countRxQuerySubscribers(rxQuery) === 1
  4. unmount
  5. assert countRxQuerySubscribers(rxQuery) === 0

That assertion failed on unmodified master (1 !== 0) and passes with this change.

Todos

  • Tests
  • Documentation
  • Typings
  • Changelog

useRxQueryBase started query.$ inside an async runQuery callback, so
useEffect never received the unsubscribe function. Return that cleanup
from the effect the same way useRxDocument already does.

Reported by chris-rnwbl in pubkey#8964.
On the non-live path runQuery ends with rxQuery.exec().then(), so
return runQuery() handed React a Promise. Only return a cleanup
function when runQuery actually produced one.
@pubkey
pubkey merged commit 7b4d400 into pubkey:master Aug 19, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

React useLiveRxQuery never unsubscribes (async runQuery drops useEffect cleanup)

2 participants