Appsilon / shiny.react

Use React in Shiny applications.
https://appsilon.github.io/shiny.react
GNU Lesser General Public License v3.0
96 stars 12 forks source link

Fix nested usage of `renderUI` with react components #33

Closed jakubsob closed 1 year ago

jakubsob commented 2 years ago

Nesting uiOutput and renderUI with shiny.fluent components breaks in some scenarios and doesn’t re-render correctly. The issue was broken down to Stack being rendered using renderUI and containing uiOutput inside of it.

The recording describes the behaviour:

Video of the issue

https://user-images.githubusercontent.com/37193264/141962049-263d4505-6f11-4469-966a-210968181e6c.mov

Reproducible example

library(shiny)
library(shiny.fluent)

ui <- fluidPage(
  PrimaryButton.shinyInput("renderCard", text = "Render card"),
  PrimaryButton.shinyInput("resetCard", text = "Reset card content"),
  textOutput("resetCardCount"),
  textOutput("renderCardCount"),
  Toggle.shinyInput("toggle", label = "Toggle dynamic content in Stack", value = TRUE),
  fluidRow(
    column(
      width = 6,
      Text("reactOutput + renderReact"),
      reactOutput("containerReact")
    ),
    column(
      width = 6,
      Text("uiOutput + renderUI"),
      uiOutput("container")
    )
  )
)

server <- function(input, output, session) { 

  resetCard <- eventReactive(input$resetCard, {
    input$resetCard
  })

  renderCard <- eventReactive(input$renderCard, {
    input$renderCard
  })

  output$renderCardCount <- renderText({
    glue::glue("Render card button clicks: {renderCard()}")
  })

  output$resetCardCount <- renderText({
    glue::glue("Reset card content button clicks: {resetCard()}")
  })

  output$containerReact <- renderReact({
    renderCard()
    Stack(
      style = list("background-color" = "grey"),
      Text(variant = "large", "Card"),
      if (isolate(input$toggle)) uiOutput("uiReact") else (Text("Static content"))
    )
  })

  output$uiReact <- renderUI({
    div(
      Text("Card content"),
      Text(variant = "large", resetCard())
    )
  })

  output$container <- renderUI({
    renderCard()
    Stack(
      style = list("background-color" = "grey"),
      Text(variant = "large", "Card"),
      if (isolate(input$toggle)) uiOutput("ui") else (Text("Static content"))
    )
  })

  output$ui <- renderUI({
    div(
      Text("Card content"),
      Text(variant = "large", resetCard())
    )
  })
}

shinyApp(ui, server)
jakubsob commented 1 year ago

Looks like it's fixed in current version. Probably fixed by https://github.com/Appsilon/shiny.react/pull/50