title: Shiny reactive outputs are not updating as expected
body: <p>I have created a shiny app that pulls software components and their versions off of a list of nodes. The goal here is to make all of our nodes consistent when possible and this app helps us see which nodes are inconsistent.</p>
  
  <p>Currently you can modify the version in the 'baseline' handsontable and it will reactively update the pivot table below with the change as well as the BaselineStats column within the handsontable. This works as expected. I have been asked to add the ability to upload a csv file that would overwrite the baseline table so a user does not have to change these 'baseline' versions each time they load the app. </p>
  
  <p>In addition, there are some components that are 100% consistent. Currently those do not appear in the 'baseline' handsontable (since this is a tool to show inconsistency) but I have added a checkbox so that the user can still report on those components that are 100% consistent. </p>
  
  <p>For some reason neither the fileUpload nor the checkboxInput are updating and no matter how much I poke and prod at my code, I cannot figure out why. </p>
  
  <p>server.R</p>
  
  <pre><code>library(shiny)
  library(rhandsontable)
  library(rpivotTable)
  library(dplyr)
  library(stringr)
  library(lubridate)
  
  shinyServer(function(input, output) {
  
    # Create dataframe
  df.consistency &lt;- structure(list(Node = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
                                      2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c("A", "B", "C", 
                                                                                      "D"), class = "factor"), Component = structure(c(3L, 4L, 1L, 2L, 3L, 
                                                                                                                                       4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L), .Label = c("docker.version", 
                                                                                                                                                                                               "kernel.version", "os.name", "os.version"), class = "factor"), 
                   Version = structure(c(10L, 3L, 1L, 6L, 10L, 3L, 1L, 7L, 10L, 
                                       5L, 1L, 8L, 10L, 4L, 2L, 9L), .Label = c("1.12.1", "1.13.1", 
                                                                                "16.04", "17.04", "18.04", "3.10.0", "3.11.0", "3.12.0", 
                                                                                "3.13.0", "RedHat"), class = "factor")), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                       -16L))
  
  # Get Date Time
  Report.Date &lt;- Sys.Date()
  
  df.baseline &lt;- reactive({
  
    inputFile &lt;- input$uploadBaselineData
  
    if(!is.null(inputFile)){
  
      read.csv(inputFile$datapath, header = input$header)
  
    } else{
      if(input$showConsistent == FALSE){
  
        # Count the number of occurrences for Version and Component, then remove the Components that are consistent (not duplicated =&gt; nn == 1) and then remove nn column
        df.clusterCons.countComponent &lt;- df.consistency %&gt;%
          add_count(Version, Component) %&gt;%
          add_count(Component) %&gt;%
          filter(nn &gt; 1) %&gt;%
          select(-nn)
  
        # Change back to dataframe after grouping
        df.clusterCons.countComponent &lt;- as.data.frame(df.clusterCons.countComponent)
  
        # Components and Versions are shown for every node/cluster. 
        # Reduce this df to get only a unique Component:Version combinations
        df.clusterCons.dist_tbl &lt;- df.clusterCons.countComponent %&gt;%
          distinct(Component, Version, .keep_all = TRUE)
  
        #Create a df that contains only duplicated rows (rows that are unique i.e. versions are consistent, are removed)
        df.clusterCons.dist_tbl.dup &lt;- df.clusterCons.dist_tbl %&gt;%
          filter(Component %in% unique(.[["Component"]][duplicated(.[["Component"]])]))
  
        #Create a baseline df to be used to filter larger dataset later 
        #(baseline = max(n) for Version -- but must retain Component since that is the parameter we will use to filter on later)
        df.clusterCons.baseline &lt;- df.clusterCons.dist_tbl.dup[order(df.clusterCons.dist_tbl.dup$Component, df.clusterCons.dist_tbl.dup$n, decreasing = TRUE),]
        df.clusterCons.baseline &lt;- df.clusterCons.baseline[!duplicated(df.clusterCons.baseline$Component), ]
        df.clusterCons.baseline &lt;- df.clusterCons.baseline %&gt;% 
          select(Component, Version)
  
  
  
      }
      else{
        # Count the number of occurrences for Version and Component, then remove the Components that are consistent (not duplicated =&gt; nn == 1) and then remove nn column
        df.clusterCons.countComponent &lt;- df.consistency %&gt;%
          add_count(Version, Component) %&gt;%
          add_count(Component) %&gt;%
          select(-nn)
  
        # Change back to dataframe after grouping
        df.clusterCons.countComponent &lt;- as.data.frame(df.clusterCons.countComponent)
  
        # Components and Versions are shown for every node/cluster. 
        # Reduce this df to get only a unique Component:Version combinations
        df.clusterCons.dist_tbl &lt;- df.clusterCons.countComponent %&gt;%
          distinct(Component, Version, .keep_all = TRUE)
  
        df.clusterCons.baseline &lt;- df.clusterCons.dist_tbl[order(df.clusterCons.dist_tbl$Component, df.clusterCons.dist_tbl$n, decreasing = TRUE),]
        df.clusterCons.baseline &lt;- df.clusterCons.baseline[!duplicated(df.clusterCons.baseline$Component), ]
        df.clusterCons.baseline &lt;- df.clusterCons.baseline %&gt;% 
          select(Component, Version)
      }
    }
  })
  
  
  df.componentVersionCounts &lt;- df.consistency %&gt;%
    add_count(Component) %&gt;%
    rename("CountComponents" = n) %&gt;%
    add_count(Component, Version) %&gt;%
    rename("CountComponentVersions" = n) %&gt;%
    mutate("BaselineStats" = paste0("Baseline: ", round(CountComponentVersions / CountComponents * 100, 2), "% of Total: ", CountComponents)) %&gt;%
    select(Component, Version, BaselineStats) %&gt;%
    distinct(.keep_all = TRUE)
  
  df.componentVersions_tbl &lt;- reactive({
    df.componentVersions_tbl &lt;- df.baseline() %&gt;%
      distinct(Component, .keep_all = TRUE) %&gt;%
      select(Component, Version) %&gt;%
      left_join(df.componentVersionCounts, by = c("Component" = "Component", "Version" = "Version"))
  
  })
  
  # Report Date Output
  output$reportDate &lt;- renderText({
    return(paste0("Report last run: ", Report.Date))
  })
  
  # handsontable showing baseline and allowing for an updated baseline
  output$baseline_table &lt;- rhandsontable::renderRHandsontable({
  
    rhandsontable(df.componentVersions_tbl(), rowHeaders = NULL) %&gt;%
      hot_col("Component", readOnly = TRUE) %&gt;%
      hot_col("BaselineStats", readOnly = TRUE) %&gt;%
      hot_cols(columnSorting = TRUE) %&gt;%
      hot_context_menu(allowRowEdit = FALSE, allowColEdit = FALSE, filters = TRUE)
  
  })
  
  observe({
    hot = isolate(input$baseline_table)
    if(!is.null(input$baseline_table)){
      handsontable &lt;- hot_to_r(input$baseline_table)
  
      df.clusterCons.baseline2 &lt;- handsontable %&gt;%
        select(-BaselineStats)
  
      df.componentVersions_tbl &lt;- df.clusterCons.baseline2  %&gt;%
        left_join(df.componentVersionCounts, by = c("Component" = "Component", "Version" = "Version"))
  
      output$baseline_table &lt;- rhandsontable::renderRHandsontable({
  
        rhandsontable(df.componentVersions_tbl, rowHeaders = NULL) %&gt;%
          hot_col("Component", readOnly = TRUE) %&gt;%
          hot_col("BaselineStats", readOnly = TRUE) %&gt;%
          hot_cols(columnSorting = TRUE) %&gt;%
          hot_context_menu(allowRowEdit = FALSE, allowColEdit = FALSE, filters = TRUE)
  
      })
  
      df.clusterIncons &lt;- anti_join(df.consistency, handsontable, by = c("Component" = "Component", "Version" = "Version"))
      df.clusterIncons &lt;- df.clusterIncons
  
      # Pivot Table showing data with inconsistencies 
      output$pivotTable &lt;- rpivotTable::renderRpivotTable({
        rpivotTable::rpivotTable(df.clusterIncons, rows = c("Cluster", "Node"), cols = "Component", aggregatorName = "List Unique Values", vals = "Version", 
                                 rendererName = "Table", 
                                 inclusions = list(Component = list("os.version", "os.name", "kernel.version", "docker.version")))
  
  
      })
  
      output$downloadBaselineData &lt;- downloadHandler(
        filename = function() {
          paste('baselineData-', Sys.Date(), '.csv', sep='')
        },
        content = function(file) {
          baseline_handsontable &lt;- handsontable %&gt;%
            select(-BaselineStats)
          write.csv(baseline_handsontable, file, row.names = FALSE)
        }
      )
  
  
      output$downloadPivotData &lt;- downloadHandler(
        filename = function() {
          paste('pivotData-', Sys.Date(), '.csv', sep='')
        },
        content = function(file) {
          write.csv(df.clusterIncons, file, row.names = FALSE)
        }
      )
  
    }
  })
  
  })
  </code></pre>
  
  <p>ui.R</p>
  
  <pre><code>library(shiny)
  library(shinydashboard)
  library(rhandsontable)
  library(rpivotTable)
  
  dashboardPage(
  
    dashboardHeader(title = "Test Dashboard", titleWidth = "97%"),
  
    dashboardSidebar(
      collapsed = TRUE,
      sidebarMenu(
        menuItem("App", tabName = "app", icon = icon("table"))
      )
    ),
  
    dashboardBody(
  
      tabItems(
        tabItem("app",
                fluidRow(
                  box(width = 3, background = "light-blue",
                      "This box includes details to the user about how the application works", br(), br(), br(), 
                      verbatimTextOutput("reportDate")
                  ),
                  box(width = 7, status = "info", title = "Version baselines based on greatest occurance",
                      rHandsontableOutput("baseline_table", height = "350px")
                  ),
                  column(width = 2, 
                         fluidRow(
                           fileInput("uploadBaselineData", "Upload Other Baseline Data:", multiple = FALSE, 
                                     accept = ".csv")
                         ),
                         fluidRow(
                           downloadButton("downloadBaselineData", "Download Baseline Data")
                         ),
                         br(), 
                         fluidRow(
                           downloadButton("downloadPivotData", "Download Pivot Table Data")
                         ),
                         br(), 
                         fluidRow(
                           checkboxInput("showConsistent", "Show Consistent Components in baseline")
                         )
                  )
                ),
                fluidRow(
                  box(width = 12, status = "info", title = "Nodes with versions inconsistent with baseline",
                      div(style = 'overflow-x: scroll', rpivotTable::rpivotTableOutput("pivotTable", height = "500px"))
                  )
                )
                )
      )
  )
      )
  </code></pre>
  
  <p>I have worked with reactivity quite often but I do not frequently use observe or isolate so that may be where I am running into an issue. I did also try out the new reactlog package but I am still not sure of a path forward. </p>
  
  <p>Here is a picture of the reactlog output before I click the check box or upload new baseline data:
  <a href="https://i.stack.imgur.com/hYWIH.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hYWIH.png" alt="Reactlog Output 1"></a> 
  And after:
  <a href="https://i.stack.imgur.com/2e3nC.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/2e3nC.png" alt="enter image description here"></a></p>