Search code examples
rshinyobserversshinystoreshinystoreplus

Why do I get an error message when using an observeEvent with this function that works fine when not wrapped in an observer?


The below example code "Code" saves to the browser the user slider input from one session to the next, using package shinyStorePlus. I would like the user to be able to clear the saved inputs via a click of the "clear" actionButton(). When the commented-out code in "Code" is uncommented, revealing the clear function in the server section, clicking that actionButton() results in error Warning: Error in envir$session$sendCustomMessage: attempt to apply non-function. However, if I pull the clear data code of clearStore(appId = appid) out of the observer and run the code this way, it works fine in clearing out the saved browser data. As an example, running the "Isolated Clearing Code" at the very bottom, completely outside the observer, clears out the browser data like it should.

What am I doing wrong here with my use of an observer? I've fooled around with using isolate(), making the appid reactive, etc., and nothing seems to work.

Code:

library(shiny)
library(shinyStorePlus)

ui <- fluidPage(
  initStore(), br(),
  
  sliderInput("input1",label=NULL,min=1,max=200,value=100),
  actionButton("clear","Clear data")
)

server <- function(input, output, session) {
  appid <- "application001"
  
  setupStorage(
    appId = appid,
    inputs = list("input1")
  )
    
  # observeEvent(input$clear,{
  # clearStore(appId = appid)
  # })
    
}

shinyApp(ui, server)

Isolated Clearing Code:

ui <- fluidPage(
  initStore(), 
)

server <- function(input, output, session) {
  appid <- "application001"
  clearStore(appId = appid)
}

shinyApp(ui, server)

Solution

  • This seems to be an issue with shinyStorePlus' code:

    > clearStore
    function (appId) 
    {
        envir <- parent.frame()
        envir$session$sendCustomMessage("clearStorage", appId)
    }
    

    using parent.frame() to get the session is unfavorable.

    Please check the following instead:

    library(shiny)
    library(shinyStorePlus)
    
    clearStore <- function(appId, session = getDefaultReactiveDomain()){
      session$sendCustomMessage("clearStorage", appId)
    }
    
    ui <- fluidPage(
      initStore(), br(),
      
      sliderInput("input1",label=NULL,min=1,max=200,value=100),
      actionButton("clear","Clear data")
    )
    
    server <- function(input, output, session) {      
      appid <- "application001"
      
      setupStorage(
        appId = appid,
        inputs = list("input1")
      )
      
      observeEvent(input$clear,{
      clearStore(appId = appid)
      })
      
    }
    
    shinyApp(ui, server)
    

    I left a PR here.