Mau314
Mau314

Reputation: 133

How to suppress a double-reaction in R-Shiny?

I have this slider which depends on the choice you make in a drop-down menu. Changing this choice essentially amounts to switching between a zero-to-one and a 0%-to-100% scale and this has an impact on the plot. I would like the plot to react only after the rescaling is complete, but it seems that it's updated before the slider-value is rescaled and then again after the slider-value is rescaled. The result is fine, but the additional step doesn't look nice.

I couldn't find a solution online. Also, if this is caused by some kind of unnecessary detour in the code, I don't see it. What can I do?

I tried to reduce the code as much as possible...

library(shiny)
library(tidyverse)
library(ggplot2)
library(flexdashboard)
library(shinythemes)
library(shinyWidgets)
library(janitor)


ui <- fluidPage(
      sidebarLayout(
         sidebarPanel(
            width = 2,
            actionButton("do", "Draw Sample", width="100%"),
            selectInput("type", label = "Type",
                        choices = c("A","B"), selected = "A"),
            sliderInput("rate", label = "Rate",
                        min = 0, max = 1, value = 0.8, step = 0.01)
            ),

         mainPanel(width = 10,uiOutput("distPlot"))
         )
      )


server <- function(input, output, session) {

    sim_data <- function() {data.frame(n = 1:100, y = runif(100))}

    v <- reactiveValues(data = NULL)

    observeEvent(input$do, {v$data = sim_data()})

    observeEvent(input$type, {

        a = input$rate

        if (input$type == "B")
            {
            updateSliderInput(session, "rate", label = "p",
                        min = 0, max = 100, value = a*100, step = 1)}
        else
            {
            updateSliderInput(session, "rate", label = "r",
                        min = 0, max = 1, value = a/100, step = 0.01)}

        },

        ignoreInit = TRUE)


    output$distPlot <- renderUI({
                        output$plot <- renderPlot({

                                           a = input$rate

                                           if (is.null(v$data)) {v$data = sim_data()}                               

                                           if (input$type == "B") {       
                                               a = quantile(v$data$y, a/100, type = 7)
                                               ggplot() + 
                                               geom_point(data = filter(v$data, y>a), aes(x = n, y = y), shape = 17, color = "firebrick1", size =4 )  + 
                                               geom_point(data = filter(v$data, y<=a), aes(x = n, y = y), shape = 16, color = "darkolivegreen4", size = 4) +
                                               geom_abline(slope=0,intercept=a)
                                               }
                                           else {
                                               ggplot() + 
                                               geom_point(data = filter(v$data, y>a), aes(x = n, y = y), shape = 17, color = "firebrick1", size = 4) + 
                                               geom_point(data = filter(v$data, y<=a), aes(x = n, y = y), shape = 16, color = "darkolivegreen4", size = 4) +    
                                               geom_abline(slope=0,intercept=a)
                                               }
                        })

                        plotOutput("plot", width = 800, height = 800)
    })

}

shinyApp(ui = ui, server = server)

Upvotes: 1

Views: 77

Answers (1)

Sada93
Sada93

Reputation: 2835

You can use isolate to shield reactive expressions against reactivity.

Replace the if statement with the following,

if (isolate(input$type) == "B") { # Isolate the reactive expression from input$type    
        a = quantile(v$data$y, a/100, type = 7)
        ggplot() + 
          geom_point(data = filter(v$data, y>a), aes(x = n, y = y), shape = 17, color = "firebrick1", size =4 )  + 
          geom_point(data = filter(v$data, y<=a), aes(x = n, y = y), shape = 16, color = "darkolivegreen4", size = 4) +
          geom_abline(slope=0,intercept=a)
}

Upvotes: 2

Related Questions