闪亮的 SelectInput 和 SelectizeInput

Shiny SelectInput and SelectizeInput

我将我的 Shiny 库更新到 1.1.0 版,我注意到 selectInput/selectizeInput 和 observeEvent/eventReactive 有一些非常奇怪的行为。

  1. 当我按退格键并清除下拉菜单的内容时出现问题。在之前的 Shiny 版本中,退格键与 eventReactive 相结合,反应式表达式不会评估(我猜它把它视为 NULL)观察和反应式将评估所需的内容。

  2. req() 也表现得很奇怪,在下面的示例 1 中,如果我们按下退格键并清除输入,则会触发 renderTable 但是当 req(input$variable) 为空时 table 消失。在以前的版本中,如果 Shiny 我相信 table 会保持不变。

复制代码:

示例 1

shinyApp(
  ui = fluidPage(
    selectizeInput("variable", "Variable:",
                c("Cylinders" = "cyl",
                  "Transmission" = "am",
                  "Gears" = "gear")),
    tableOutput("data")
  ),
  server = function(input, output) {
    observeEvent(input$variable,{
      cat("Printing: ",input$variable,"\n")
    })

    output$data <- renderTable({
      req(input$variable)
      Sys.sleep(2)
      mtcars[, c("mpg", input$variable), drop = FALSE]
    }, rownames = TRUE)
  }
)

示例 2

这看起来不错,但如果您注意到在按下退格键时仍在调用 renderTable。如果这是一项昂贵的计算,那将是不受欢迎的行为。

    shinyApp(
  ui = fluidPage(
    selectInput("variable", "Variable:",
                   c("Cylinders" = "cyl",
                     "Transmission" = "am",
                     "Gears" = "gear")),
    tableOutput("data")
  ),
  server = function(input, output) {
    observeEvent(input$variable,{
      cat("Printing: ",input$variable,"\n")
    })

    output$data <- renderTable({
      req(input$variable)
      Sys.sleep(2)
      mtcars[, c("mpg", input$variable), drop = FALSE]
    }, rownames = TRUE)
  }
)

我想要的行为:当按下退格键清除菜单时,不会触发 observeEvents 和 eventReactive。

目前的行为似乎触发了退格事件,但输入值保持不变。此行为实际上可能是 JavaScript 函数 Shiny.onInputChange 更新时发生的意外更改。 NEWS on shinys github site 在版本 1.1 下声明以下内容。

NEW FEATURES

[...]

Introduced two changes to the (undocumented but widely used) JavaScript function Shiny.onInputChange(name, value). First, we changed the function name to Shiny.setInputValue (but don't worry--the old function name will continue to work). Second, until now, all calls to Shiny.onInputChange(inputId, value) have been "deduplicated"; that is, anytime an input is set to the same value it already has, the set is ignored. With Shiny v1.1, you can now add an options object as the third parameter: Shiny.setInputValue("name", value, {priority: "event"}). When the priority option is set to "event", Shiny will always send the value and trigger reactivity, whether it is a duplicate or not.

selectInput 的当前版本似乎利用了这个新的 {priority: "event"} 选项,但这只是猜测。

解决方法

您可以通过自己对输入进行重复数据删除来调整您的服务器代码以正确处理这种新行为。

dedupedValue <- reactiveVal()
observe({ dedupedValue(input$value) })

然后在其余的服务器代码中使用 dedupedValue() 而不是 input$value。这也适用于旧版本的闪亮。

注意: 如果您尝试在上面的代码中使用 reactive 而不是 observe,它将不起作用。

长期解决方案

也许最好将这个问题搁置,直到闪亮的开发人员查看 your GitHub issue。如上所述,造成这种情况的原因可能是 shiny 的 JavaScript 一侧的界面更改。如果这确实造成了代码中断更改,我相信开发人员会提供修复程序以确保向后兼容。

关于req

这基本上与手头的问题无关,但提出了您的问题:如果您希望 req 在条件不“真实”的情况下重新训练旧输出,您应该将其称为

req(condition, cancelOuput = TRUE)