lucacerone
lucacerone

Reputation: 10109

Shiny App: eventReactive and reactive inconsistent behaviour with actionButton to "Refresh"

I would like to understand why I get different behaviors than I expect when using eventReactive instead of reactive together with an actionButton to refresh the page.

For example, this simple Shiny dashboard behaves as I expect: upon loading the plot is displayed and I can modify the filter and refresh the plot when clicking on the refresh button.

# app1.R

library(shiny)
library(dplyr)
library(ggplot2)

species <- levels(iris$Species)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("species", "Select Iris Species", 
          choices = species, selected=species, multiple = TRUE),
      actionButton("refresh", "Refresh")
    ),
    mainPanel(plotOutput("scatterplot"))
  )
)

server <- function(input, output) {

  selected_data <- reactive({
    input$refresh
    isolate({
    iris %>% filter(Species %in% input$species)
  })
  })

  output$scatterplot <- renderPlot({
    plot(selected_data())
  })
}

shinyApp(ui = ui, server = server)

Based on my understanding of actionButton and eventReactive I though I could replace the code for selected_data with

selected_data <- eventReactive( input$refresh, {
  iris %>% filter(Species %in% input$species)
})

this way I make explicit that selected_data only depends on input$refresh.

However the app doesn't behave as I expect: upon loading no plot is shown and I have to explicitely click on "Refresh" to get the plot displayed. After that everything works as intended.

Here is the full code for the second version of the app:

# app2.R

library(shiny)
library(dplyr)
library(ggplot2)

species <- levels(iris$Species)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("species", "Select Iris Species", 
          choices = species, selected=species, multiple = TRUE),
      actionButton("refresh", "Refresh")
    ),
    mainPanel(plotOutput("scatterplot"))
  )
)

server <- function(input, output) {

  selected_data <- eventReactive( input$refresh, {

    iris %>% filter(Species %in% input$species)

  })

  output$scatterplot <- renderPlot({
    plot(selected_data())
  })
}

shinyApp(ui = ui, server = server)

According to the documentation, when the Shiny app is executed input$refresh should have changed value from NULL to 0, which in turns triggers the evaluation of selected_data and showing the plot.

Can you explain me why in app1.R the plot is shown when the app is loaded and in app2.R you have to force the refresh manually?

Is there any (clean) way I can make app2.R show the plot when the app is loaded?

Upvotes: 2

Views: 1347

Answers (1)

Pork Chop
Pork Chop

Reputation: 29387

There is an argument within eventReactive which is ignoreNULL and it is set to TRUE by default, if you change that to FALSE it will trigger. For more info please refer to ?eventReactive

library(shiny)
library(dplyr)
library(ggplot2)

species <- levels(iris$Species)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("species", "Select Iris Species", 
                  choices = species, selected=species, multiple = TRUE),
      actionButton("refresh", "Refresh")
    ),
    mainPanel(plotOutput("scatterplot"))
  )
)

server <- function(input, output) {

  selected_data <- eventReactive( input$refresh, {
    iris %>% filter(Species %in% input$species)
  },ignoreNULL = F)

  output$scatterplot <- renderPlot({
    plot(selected_data())
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 3

Related Questions