Hi,
By design, Shiny will only run all code once unless it has reactive content that is updated. This does mean that the code for all tabs is generated at launch, but then not anymore.
You can force Shiny to wait with the execution of tab code till you click the tab, if indeed it's very computationally expensive code and the user is not likely to click it anyway.
Find below a dummy example how this could be implemented (you can of course make it much more complex than that)
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable")
),
tabPanel(value = "tab2", title = "Tab 2",
plotOutput("myPlot")
)
)
)
server <- function(input, output, session) {
tableData = reactiveVal()
plotData = reactiveVal()
observeEvent(input$tabs, {
if(input$tabs == "tab1"){
#Code for tab 1
req(is.null(tableData()))
print("Tab 1 code is run")
tableData(data.frame(x = 1:10, y = LETTERS[1:10]))
} else if(input$tabs == "tab2"){
#Code for tab 2
req(is.null(plotData()))
print("Tab 2 code is run")
plotData(runif(100))
}
})
output$myTable = renderTable({
tableData()
})
output$myPlot = renderPlot({
plot(plotData())
})
}
shinyApp(ui, server)
Since the code in tab 1 will always have to be rendered at start anyway, you can also write the code like this:
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable")
),
tabPanel(value = "tab2", title = "Tab 2",
plotOutput("myPlot")
)
)
)
server <- function(input, output, session) {
tableData = reactiveVal(data.frame(x = 1:10, y = LETTERS[1:10]))
plotData = reactiveVal()
observeEvent(input$tabs, {
if(input$tabs == "tab2"){
#Code for tab 2
req(is.null(plotData()))
print("Tab 2 code is run")
plotData(runif(100))
}
})
output$myTable = renderTable({
tableData()
})
output$myPlot = renderPlot({
plot(plotData())
})
}
shinyApp(ui, server)
Hope this helps,
PJ