Reactive with invalidateLater triggers events even if the reactive value itself does not change

Hi!

I am working on a shiny app that periodically checks a Github repo where I store the data for new pushes (i.e. new data arrived), but only reruns the calculations if new data arrived.

My problem is that if I use invalidateLater in a reactive to check for the push time, and I use that reactive to trigger a reactiveEvent that runs the calculations, the reactiveEvent is triggered even, if the push time itself did not change.

I made a small reprex with a constant push time.

Do you have any suggestions on how to solve this problem?
Thanks!

shinyApp(
  ui = fluidPage(
    plotOutput("plot")
  ),
  
  server = function(input, output, session) {
    # Get latest update time
    push_time <- reactive({
      invalidateLater(1000)
      # In the real code here I get the latest push
      # time from a Github repo
      # For reprex here is a unix timestamp
      1601627006
    })
    
    # Update data only if push_time is updated
    # i.e. new data arrived
    my_data <- eventReactive(push_time(), {
      runif(1000, 0, 1)
    })
    
    # Render plot
    output$plot <- renderPlot(plot(my_data()))
  }
)

Hi @martonbalazskovacs,

I think what you are looking for is a reactive value. The calling reactive expr will depend on the value. What you've done here is a reactive expression that gets invalidated although it is replaced by the same expression.

library(shiny)
shinyApp(
  ui = fluidPage(
    plotOutput("plot")
  ),
  
  server = function(input, output, session) {
  # init with any value, here your value
    push_time <- reactiveVal(1601627006)
    
    # I don't like unspecific observers but I could not think of any better for the moment
    observe({
      invalidateLater(1000)
      # print every tick
      print(sprintf("%s: Tick. Value: %s", Sys.time(), isolate(push_time())))
      
      # mimic an update by chance
      if (runif(1) > 0.8) {
        # update the value
        push_time(1601627006)
      } else {
        push_time(0)
      }
    })
    
    # Update data only if push_time is updated
    # i.e. new data arrived
    my_data <- eventReactive(push_time(), {
      print(sprintf("%s: Update. Value: %s", Sys.time(), isolate(push_time())))
      runif(1000, 0, 1)
    })
    
    # Render plot
    output$plot <- renderPlot(plot(my_data()))
  }
)

Created on 2020-10-02 by the reprex package (v0.3.0)

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.