Skip to content

Example: host a reactable (reactR htmlwidget) inside a shinyreact client via ShinyOutput #317

Description

@schloerke

Motivation

#316 added a comparison article whose "Can they be combined?" section documents hosting a reactable inside a ui.tsx client through ShinyOutput. That was verified in a throwaway chromote spike, not shipped. An example would keep the claim honest (the repo's example tests run in each package's suite) and give people a template for the most common "I already have an R widget" case. 07-plotly covers htmlwidgets from the plot side; reactable covers the table side and, unlike plotly, has a client→server state channel (getReactableState()) that needs one extra attribute to work.

What the spike showed

  • renderReactable() is a regular shiny.render.function, so shinyreact's R dep discovery loads htmlwidgets.js, react-tools.js, and reactable.js automatically. No manual dependency wiring.
  • The ShinyOutput element needs the classes reactableOutput() emits and a data-reactable-output="<id>" attribute. Without the attribute the table renders but getReactableState() / updateReactable() never see it, because reactable reads its Shiny id from that attribute on the container's parent.
  • Row selection round-trips: click a selection radio → input$tbl__reactable__selectedgetReactableState("tbl", "selected") → a reactive_outputuseShinyOutputValue.

Working spike (R server, no-build client):

server <- function(input, output, session) {
  output$tbl <- reactable::renderReactable({
    reactable::reactable(head(mtcars, req(input$n)), selection = "single", onClick = "select")
  })
  output$sel <- reactive_output(reactable::getReactableState("tbl", "selected"))
}
shinyApp(page_react(), server)
h(ShinyOutput, {
  id: "tbl",
  className: "reactable html-widget html-widget-output",
  "data-reactable-output": "tbl",
});

Proposed shape

  • examples/11-reactable/ (or fold into an existing example if that reads better): app.R, www/ui.js, FEATURES.md, tests/.
  • A row-count input driving the table, a reactive_output echoing the selected row so the client→server channel is exercised, and a useShinyOutputStatus dim on recalculation.
  • Add to R_EXAMPLES in the Makefile and run make update-examples so R CMD check can reach it.
  • Python side: there is no reactable for Python. Either R-only (note it in examples/README.md) or pair it with a Python ShinyOutput-hosted equivalent (shinywidgets? great_tables?) over the same ui.js, mirroring how 07-plotly shares one client across both servers.
  • Testing: ui.test.ts against the fake-Shiny harness can pin the classes and the data-reactable-output attribute; a testthat test can pin that renderReactable()'s deps are discovered. The selection round-trip is a browser claim and would wait on the R e2e suite (Add an R Playwright e2e suite #194).

Open questions

  • Should ShinyOutput grow a documented recipe (skill or article) for "copy the attributes your *Output() would have emitted", since both reactable and plotly needed exactly that and it is not discoverable without reading widget source?
  • Is a shiny.react / shiny.fluent example worth shipping too, or is the article section enough? It needs the manual reactDependency() + shinyReactDependency() step because renderReact() is not a shiny.render.function.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions