I work on a Shiny application with shinydashboard
and somewhere in the app I want to show a notification telling the user how many other users are connected to the application at the same time.
I came up with a first piece of code that seems to work:
library(shiny)
ui=fluidPage(uiOutput("text"))
number.users <- 0 # global variable
server= function(input, output, session){
already.counted = FALSE
autoInvalidate = reactiveTimer(2000)
observe({
if (!already.counted) {
already.counted <- TRUE
number.users <<- number.users + 1
}
})
output$text = renderUI({
autoInvalidate()
h1(paste0("There are ", number.users, " user(s) connected to this app"))
})
onSessionEnded(function(){number.users <<- number.users - 1})
}
However it's not very "clean" and I'm afraid that my call to observe
and the invalidate every 2 secs are adding some useless computing time to my (already heavy) app. I was wondering if there was some kind of function in shiny
that triggers an event at the start of each new session, something like onsessionstart() that I could use directly to increment the global variable number.users
, and a way to notify other sessions that a new session has been opened? Or is there any simpler way to go?
Thanks
The root server function is called once for every new session, and effectively serves as the "onSessionStart" callback. I think what you're doing is fine, except the observe
isn't really necessary.
To share global state between sessions in a more reactive manner, you can initialize a reactiveVal
or reactiveValues
object in global scope (outside of a reactive context), and then take a reactive dependency on it within each session. Any updates to these reactive values will immediately propagate to all other sessions.
library(shiny)
users = reactiveValues(count = 0)
ui = fluidPage(uiOutput("text"))
server = function(input, output, session) {
onSessionStart = isolate({
users$count = users$count + 1
})
onSessionEnded(function() {
isolate({
users$count = users$count - 1
})
})
output$text = renderUI({
h1(paste0("There are ", users$count, " user(s) connected to this app"))
})
}
shinyApp(ui, server)
Btw, a more complex example of inter-session communication, though maybe a bit old now, is the Shiny chat room app - http://shiny.rstudio.com/gallery/chat-room.html