Skip to content

feat(js): add useShinyConnected(); hear Shiny's jQuery lifecycle events - #333

Open
schloerke wants to merge 2 commits into
schloerke/image-output-errorfrom
schloerke/use-shiny-connected
Open

schloerke wants to merge 2 commits into
schloerke/image-output-errorfrom
schloerke/use-shiny-connected

Conversation

@schloerke

@schloerke schloerke commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes posit-dev/shinyreact#328.

Root cause: Shiny fires shiny:connected, shiny:disconnected, shiny:busy, and shiny:idle with jQuery's trigger(). That only calls jQuery handlers; document.addEventListener() never sees them. The lifecycle store listened with addEventListener(), so:

  • there was no way to see a disconnect (the issue), and
  • useShinyBusy() never updated in a real browser either. Its unit tests passed because they send native events.

Changes:

  • A small onShinyEvent() helper listens through window.jQuery(document).on() when jQuery is on the page, and falls back to addEventListener() otherwise. jQuery handlers also get native events, so the jsdom tests still work.
  • The lifecycle store and the dependency-discovery shiny:connected wait both use it.
  • New useShinyConnected() hook: false until the socket opens, false again on disconnect, true again if Shiny reconnects. It seeds from Shiny.shinyapp.isConnected() for late mounts. useShinyInitialized() is unchanged (it stays true).
  • The hook is exported on window.shinyreact and the npm entry, and taught in the shinyreact-build-app skill.

Checked by hand in a browser with an R app: "Busy" now shows during a slow request, and stopping the R process flips the hook to false.

@schloerke
schloerke added this pull request to stack #335 November 9, 2026 18:21
@schloerke
schloerke force-pushed the schloerke/use-shiny-connected branch from b304c7d to 3a8dd0a Compare November 9, 2026 21:41
Shiny fires shiny:connected / disconnected / busy / idle with jQuery's
trigger(), which never reaches addEventListener() listeners. So
useShinyBusy() never updated in a real browser, and nothing could tell the
session had dropped. The lifecycle store now listens through
window.jQuery(document).on() when jQuery is present, and tracks a new
connected flag exposed as useShinyConnected().

Fixes #328
…y; warn when jQuery is missing

The jsdom tests send native events, the very thing that hid #328. The new
Playwright test drives a slow output and a session close in a real browser,
and fails with native-only listeners.

onShinyEvent() now warns when window.Shiny is present but window.jQuery is
not, and documents the second-jQuery case it does not handle.
@schloerke
schloerke force-pushed the schloerke/use-shiny-connected branch from 3a8dd0a to e1741f2 Compare November 12, 2026 16:08

This branch has not been deployed

No deployments
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.

No way to detect a disconnected session from React

1 participant