Can I save the old value of a reactive object when it changes?

后端 未结 2 2146
不思量自难忘°
不思量自难忘° 2021-02-13 04:56

Note: After coming up with the answer I reworded the question to make if clearer.

Sometimes in a shiny app. I want to make use of a value s

相关标签:
2条回答
  • 2021-02-13 05:06

    Seeing as the session flush event method seems to be broken for this purpose, here is an alternative way to do it using an observeEvent construct and a reactive variable.

    library(shiny)
    
    ui <- fluidPage(
      h1("Memory"),
      sidebarLayout(
        sidebarPanel(
          numericInput("val", "Next Value", 10)
        ),
        mainPanel(
          verbatimTextOutput("curval"),
          verbatimTextOutput("lstval")
        )
      )
    )
    
    server <- function(input,output,session) {
      rv <- reactiveValues(lstval=0,curval=0)
    
      observeEvent(input$val, {rv$lstval <- rv$curval; rv$curval <- input$val})
    
      curre <- reactive({req(input$val);  input$val; rv$curval})
      lstre <- reactive({req(input$val);  input$val; rv$lstval})
    
      output$curval <- renderPrint({sprintf("cur:%d",curre())})
      output$lstval <- renderPrint({sprintf("lst:%d",lstre())})
    }
    options(shiny.reactlog = TRUE)
    shinyApp(ui, server)
    

    Yielding:

    0 讨论(0)
  • 2021-02-13 05:27

    Update This answer was posted before the advent of the reactiveValues/observeEvent model in shiny. I think that @MikeWise 's answer is the better way to do this.

    After some playing around this is what I came up with. The ui.r is nothing special

    ui.r

    library(shiny)
    
    ui <- shinyUI(fluidPage(
      sidebarLayout(
        sidebarPanel(
          selectizeInput(inputId="XX", label="Choose a letter",choices=letters[1:5])
        ),
        mainPanel(
          textOutput("Current"),
          textOutput("old")
        )
      ) 
    ))  
    

    "Current" will display the current selection and "old" displays the previous selection.

    In the server.r I made use of three key functions: reactiveValues, isolate and session$onFlush.

    server.r

    library(shiny)
    
    server <- function(input, output,session) {
    
      Values<-reactiveValues(old="Start")
    
      session$onFlush(once=FALSE, function(){
        isolate({ Values$old<-input$XX })
      })
    
    
      output$Current <- renderText({paste("Current:",input$XX)})
    
      output$old <- renderText({ paste("Old:",Values$old) })
    }  
    

    The server.r works like this.

    First, Values$old is created using the reactiveValues function. I gave it the value "Start" to make it clear what was happening on load up.

    Then I added a session$onFlush function. Note that I have session as an argument in my server function. This will run every time that shiny flushes the reactive system - such as when the selectizeInput is changed by the user. What is important is that it will run before input$XX gets a new value - so the value has changed at the selectizeInput but not at XX.

    Inside the session$onFlush I then assign the outgoing value of XX to Values$old. This is done inside an isolate() as this will prevent any problems with input$XX gets updated with the new values. I can then use input$XX and Values$old in the renderText() functions.

    0 讨论(0)
提交回复
热议问题