Upgrade notes for Shiny 1.8.1

New features and improvements

  • Added ExtendedTask, a new simple way to launch long-running asynchronous tasks that are truly non-blocking. That is, even within a session, an ExtendedTask won’t block the main thread from flushing the reactive graph (i.e., UI updates won’t be blocked). ExtendedTask pairs nicely with new bslib::input_task_button() and bslib::bind_task_button() functions, which help give user feedback and prevent extra button clicks. (#3958)

  • Added a JavaScript error dialog, reporting errors that previously were only discoverable by opening the browser’s devtools open. Since this dialog is mainly useful for debugging and development, it must be enabled with shiny::devmode(). (#3931)

  • runExamples() now uses the bslib package to generate a better looking result. It also gains a package argument so that other packages can leverage this same function to run Shiny app examples. For more, see ?runExamples. (#3963, #4005)

  • Added onUnhandledError() to register a function that will be called when an unhandled error occurs in a Shiny app. Note that this handler doesn’t stop the error or prevent the session from closing, but it can be used to log the error or to clean up session-specific resources. (thanks @JohnCoene, #3993)


  • renderDataTable()/dataTableOutput() are officially deprecated in favor of their {DT} equivalents. Migrating to DT, in most cases, just requires changing renderDataTable() to DT::renderDT() and dataTableOutput() to DT::DTOutput(). Also, to promote migration, when a recent version of DT is available, renderDataTable()/dataTableOutput() now automatically use their DT equivalent (and provide a message that they are doing so). If this happens to degrade an existing app, set options(shiny.legacy.datatable = TRUE) to get the old (i.e., non-DT) implementation. (#3998)

  • Both conditionalPanel() and uiOutput() are now styled with display: contents by default in Shiny apps that use Bootstrap 5. This means that the elements they contain are positioned as if they were direct children of the parent container holding the conditionalPanel() or uiOutput(). This is probably what most users intend when they use these functions, but it may break apps that applied styles directly to the container elements created by these two functions. In that case, you may include CSS rules to set display: block for the .shiny-panel-conditional or .shiny-html-output classes. (#3957, #3960)

Bug fixes

  • Notifications are now constrained to the width of the viewport for window widths smaller the default notification panel size. (#3949)

  • Fixed #2392: downloadButton() now visibly returns its HTML tag so that it renders correctly in R Markdown and Quarto output. (Thanks to @fennovj, #2672)

  • Calling updateSelectizeInput() with choices and selected now clears the current selection before updating the choices and selected value. (#3967)

  • Loading a Shiny app in a package-like directory will no longer warn if autoloading is disabled by the presence of an R/_disable_autoload.R file. (Thanks to @krlmlr and @tanho63, #3513)