在开发应用程序时,我注意到Shiny会在不需要时重新计算输出(我认为),而且它似乎取决于reactiveValues
中的嵌套。
library(shiny)
n <- 5
o <- paste0('o', 1:n)
ui <- fluidPage(
lapply(o, function(x) textOutput(x)),
actionButton('a1', 'a1')
)
server <- function(input, output){
rv <- reactiveValues(o1='a', o2='b', o3='c', o4='d', o5='e')
lapply(o, function(x){
output[[x]] <- renderText({
cat('rendering', x, '\n')
rv[[x]]
})
})
observeEvent(input$a1, {
rv$o1 <- rnorm(1)
})
}
server <- function(input, output){
rv <- reactiveValues(
# difference with server one is that o1-5 are nested in l
l=list(o1='a', o2='b', o3='c', o4='d', o5='e')
)
lapply(o, function(x){
output[[x]] <- renderText({
cat('rendering', x, '\n')
rv$l[[x]]
})
})
observeEvent(input$a1, {
rv$l$o1 <- rnorm(1)
})
}
使用服务器一运行应用程序时,每次单击该按钮时,仅重新计算o1
(如控制台中显示的那样)。但是,当在服务器2上运行该应用程序时,每次单击该按钮,都会重新计算所有输出。
我当时想知道光泽如何确定依赖关系。它可以仅区分reactiveValues
的较高级别的依存关系,还是有办法使输出仅取决于reactiveValues
的更深层次?换句话说,如果我需要/想要使用服务器2中的情况,是否可以防止单击按钮时重新计算o1
以外的其他输出?
答案 0 :(得分:1)
对于shiny
的{{1}},每个单个对象作为一个整体是反应性组件:如果其结构内有任何东西(是否为reactiveValues
,{ {1}},vector
等)进行更改,则整个对象被视为已更改(因此,事物将对此做出反应)。
要讨论是否有可能对子组件做出反应,请考虑以下事项:然后将任何对象递归地视为 。对list
的顶级组件做出反应的第一个示例并没有那么糟糕……但是,如果要跟踪的事物具有多个层次(并且没有理由或保障措施可以防止这种情况发生),那么每次某事发生时,让data.frame
深入研究对象的每个单独组成部分都会带来很多开销。伸缩性很差。
出于组织目的,请意识到您可以具有多个独立的list
组件。尽管我怀疑它是否会对性能产生很大影响,但可以这样做:
shiny
坦率地说,在某些情况下这可能会更好:紧凑性(一个超大的reactiveValues
调用)可能会稍快一些(尽管我仍然不知道这是真的) ),有人可能会说 readability 直接影响 maintainability 和 troubleshooting 。如果反应性值具有声明性分组,则在您(或其他人)几个月不活动后查看代码时,可能会有很大的不同。