0

There are two ways in which a variable can be accessed across all server functions in a Shiny app.

One would be defining it inside the server, and then accessing it with <<- operator. It does not become shared across all sessions when doing so. Not being shared across all sessions is the intended behavior.

library(shiny)

ui <- fluidPage(
    actionButton("btn", "Increase num"),
    actionButton("msg", "Show num")
)

server <- function(input, output) {
    n <- 0
    observeEvent(input$btn, { n <<- n+1 } )
    observeEvent(input$msg, { showModal(modalDialog(title=n, easyClose = T)) } )
}
shinyApp(ui = ui, server = server)

The other would be creating a reactive variable

library(shiny)
ui <- fluidPage(
    actionButton("btn", "Increase num"),
    actionButton("msg", "Show num")
)

server <- function(input, output) {
    n <- reactiveVal(0)
    observeEvent(input$btn, { n(n()+1) } )
    observeEvent(input$msg, { showModal(modalDialog(title=n(), easyClose = T)) } )
}
shinyApp(ui = ui, server = server)

Which one would be better, and why?

Sam
  • 127
  • 10
  • It seems that reactivity is more Shiny style, generally speaking. But is not the main goal of reactivity tracking changes to variables, rather than defining the scope of one's variables? – Sam Jul 03 '22 at 15:23

2 Answers2

1

You can declare variables including the reactive expressions outside the server.R which then can be invalidated across all sessions, alternatively, you can use them inside the server.R then they will be unique per session. Not 100% what sort of behavior are you looking for...

library(shiny)

globalreactive <- reactiveValues(n=0)

ui <- fluidPage(
  column(6,
         actionButton("global_button", "Increase global num"),
         textOutput("global_value")
  ),
  column(6,
         actionButton("local_button", "Increase local num"),
         textOutput("local_value")
  )
)

server <- function(input, output, session) {
  
  localreactive <- reactiveValues(n=0)
  
  observeEvent(input$global_button,{ 
    globalreactive$n <- globalreactive$n+1 
  })
  
  observeEvent(input$local_button,{ 
    localreactive$n <- localreactive$n+1 
  })
  
  output$global_value <- renderText({
    globalreactive$n
  })
  
  output$local_value <- renderText({
    localreactive$n
  })
  
}
shinyApp(ui = ui, server = server)

enter image description here

Pork Chop
  • 28,528
  • 5
  • 63
  • 77
  • The intended use is that the variables are **not** shared across sessions. Sorry for not clarifying it. – Sam Jul 04 '22 at 13:35
0

I suppose this question is likely to be closed as "likely to lead to opinion-based answers".

That being said, ...

  1. Using a reactive expression X is only required when there is some reactive consumer that needs to be called by Shiny when X changes. If you do not need this, I would recommend against using it because it always creates quite a bit of computational overhead by Shiny.

  2. Hence, using a variable inside the server function is the first option, unless you need 1.

  3. The scope would be limited to a single instance of your Shiny app, because "Shiny, by default, creates one process per Shiny app" (quote by Jeff Allen).

  4. There'd be the option of a global variable. Of course, the dis-/advantages of global variables need not be discussed here. It would have the advantage, though, of being shared across sessions.

Jan
  • 4,974
  • 3
  • 26
  • 43