To all R Shiny experts: Which of the following three server functions would you rate first, second and third - and why?
I had an intensive discussion today about which of the three solutions comes closest to "best practice" Shiny app design. (While they all three work the same.)
For example, version C seems odd to me since overwriting render functions conditionally is unnecessary (since conditional output rendering is what these functions were made for).
The original app contains much more logic when dealing with input values, of course. I simplified the example to make the differences obvious.
library(shiny)
ui <- fluidPage(
shiny::radioButtons(
inputId = "some_input",
label = "Please choose:",
choices = c("something", "nothing")
),
shiny::textOutput(
outputId = "some_output"
)
)
# version A: all logic within rendering function
server <- function(input, output, session) {
output$some_output <- shiny::renderText({
if(input$some_input == "something"){
# imagine some complex logic here
"some value was chosen"
} else {
NULL
}
})
}
# version B: most logic within input observer,
# using reactive session userData
server <- function(input, output, session) {
session$userData$memory <- shiny::reactiveValues(
"stored_value" = NULL
)
output$some_output <- shiny::renderText({
session$userData$memory$stored_value
})
shiny::observeEvent({
input$some_input
}, {
if(input$some_input == "something"){
# imagine some complex logic here
session$userData$memory$stored_value <- "some value was chosen"
} else {
session$userData$memory$stored_value <- NULL
}
})
}
# version C: all logic within observer,
# setting the rendering function conditionally
server <- function(input, output, session) {
shiny::observeEvent({
input$some_input
}, {
if(input$some_input == "something"){
# imagine some complex logic here
output$some_output <- shiny::renderText({ "some value was chosen" })
} else {
output$some_output <- shiny::renderText({ NULL })
}
})
}
shinyApp(ui = ui, server = server)