I'm relatively new to R Shiny and reactive programming. From my understanding (and this tutorial), it seems like you are not supposed to tell Shiny "when" to do things (i.e. to enforce execution order) as it will figure that out itself. However, often I find myself wanting plots or other UI to render sequentially. Is there a good way to do this?
I've made up a minimal example below. I want to render header
before plot
, as plot
requires a time-consuming computation.
library(shiny)
ui <- fluidPage(
tags$h1("My app"),
uiOutput("header"),
plotOutput("plot")
)
server <- function(input, output) {
output$header <- renderUI({
tagList(tags$h2("Section header"),
tags$p("Some information relevant to the plot below..."))
})
output$plot <- renderPlot({
# hypothetical expensive computation
Sys.sleep(2)
# hypothetical plot
hist(rnorm(20))
})
}
shinyApp(ui = ui, server = server)
Here I could obviously replace uiOutput("header")
in ui
with its definition in server
and that solves the problem; however, in practice I want header
to be dynamic. A hacky solution I found was to include a hidden input inside header
and then use req()
inside plot
. This is kind of like adding an action button that automatically clicks upon load.
server <- function(input, output) {
output$header <- renderUI({
tagList(tags$h2("Section header"),
tags$p("Some information relevant to the plot below..."),
div(style = "display:none", textInput(inputId = "hidden", label = "", value = "x")))
})
output$plot <- renderPlot({
req(input$hidden)
...
})
}
However, if I want to repeat this in multiple situations or if I want to force a chain of more than two outputs to render sequentially, then this seems tedious. Can anyone suggest a more elegant solution?
question from:
https://stackoverflow.com/questions/65839072/forcing-render-order-in-r-shiny 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…