我对R Shiny和响应式编程相对较新。根据我的理解(以及这个教程),似乎你不应该告诉Shiny“何时”去执行某些操作(即强制执行顺序),因为它会自己解决这个问题。然而,通常情况下,我希望绘图或其他UI逐个渲染。有没有一个好的方法来实现这一点?
我下面提供了一个最小化的示例。我想先渲染header
然后再渲染plot
,因为plot
需要耗费大量的计算时间。
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)
很明显,我可以用server
中的定义替换ui
中的uiOutput("header")
,这样问题就解决了; 但是,实际上我想让header
是动态的。我找到的一个妥协的解决方案是在header
中包含一个隐藏的输入,并在plot
中使用req()
。这有点像在加载时自动单击操作按钮。
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)
...
})
}
然而,如果我想在多种情况下重复这个过程,或者如果我想要强制连续渲染两个以上的输出,则这似乎很繁琐。有没有人可以提供更加优雅的解决方案?
uiOutput("header")
上方添加文本。您会注意到,在绘图准备好之前,标题栏保持空白。 - antsatsuirenderPlot
和renderUI
没有priority
参数,但是observeEvent
有。也许如果你让你的图表和标题分别依赖于由具有不同优先级的observeEvent
生成的反应性,那么这将给你想要的结果。 - Limeyobserve
调用来修改reactiveValues,然后从每个render
中调用reactiveValues。不幸的是,尝试改变优先级并没有改变任何东西——标题总是首先执行,但在显示之前等待图形完成。我尝试的另一种方法是只需将output$header <- ...
(以及同样的操作)包装在observe语句中——然后priority
让我改变执行顺序,但我仍然有它们互相等待加载的问题。 - antsatsui