While working on an app, I noticed shiny recalculates an output when it is not necessary (in my opinion), and it seems to depend on the nesting in reactiveValues
.
UI:
library(shiny)
n <- 5
o <- paste0('o', 1:n)
ui <- fluidPage(
lapply(o, function(x) textOutput(x)),
actionButton('a1', 'a1')
)
Server one (recalculating outputs as I would expect):
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 two (each output is recalculated when clicking button):
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)
})
}
When running the app with server one, each time the button is clicked, only o1
is recalculated (as is printed in the console). However, when running the app with server two, each time the button is clicked, all outputs are recalculated.
I was wondering then how shiny determines dependencies. Can it only distinguish dependencies at the upper level of the reactiveValues
or is there a way to make the output only depend on a deeper level of reactiveValues
? In other words, if I need/want a situation as in server two, can I prevent outputs other than o1
to recalculate when the button is clicked?