Conditional Reactivity

Shiny's reactive expressions propagate changes where they need to go. We can suppress some of this behavior with isolate , but can we suppress propagated changes based on our own logical expression?

The example I give is a simple scatter chart, and we draw a crosshair with abline where the user clicks. Unfortunately, Shiny believes that the result is a new plot, and our click value is reset to NULL ... which, in turn, is considered an update for the value that will be distributed as usual. The plot is redrawn, and NULL is passed to both abline arguments.

My hack (commented below) is to put a condition in a call to renderPlot , which updates some non-reactive variables to build coordinates only when click values ​​are not NULL . This is great for trivial graphs, but in fact it leads to the fact that the graph is drawn twice.

What is the best way to do this? Is it right?

Server file:

 library(shiny) shinyServer(function (input, output) { xclick <- yclick <- NULL output$plot <- renderPlot({ #if (!is.null(input$click$x)){ xclick <<- input$click$x yclick <<- input$click$y #} plot(1, 1) abline(v = xclick, h = yclick) }) }) 

UI file:

 library(shiny) shinyUI( basicPage( plotOutput("plot", click = "click", height = "400px", width = "400px") ) ) 
+5
source share
1 answer

Winston calls this problem β€œstate” accumulation - you want to display not only current data, but also something generated by the previous graph (the best place to find out about this is https://www.rstudio.com/resources/videos/ coordinated-multiple-views-linked-brushing / )

The main idea is to create your own set of reactive values ​​and update them when the user clicks on the plot. They will not be canceled until the next click, so you will not get circular behavior.

 library(shiny) shinyApp( shinyUI(basicPage(plotOutput("plot", click = "click"))), function(input, output) { click <- reactiveValues(x = NULL, y = NULL) observeEvent(input$click, { click$x <- input$click$x click$y <- input$click$y }) output$plot <- renderPlot({ plot(1, 1) abline(v = click$x, h = click$y) }) } ) 
+2
source

All Articles