我将Shiny库更新为1.1.0版,我注意到selectInput / selectizeInput和watchEvent / eventReactive的行为非常奇怪。
当我按退格键并清除下拉菜单的内容时,会出现问题。在以前的Shiny版本中,退格键与eventReactive结合使用,反应式表达式不会评估观察值(我认为将其视为NULL),而反应式会评估期望的结果。
req()也很奇怪,在下面的示例1中,如果我们按退格键并清除输入,则将触发renderTable,但是当req(input $ variable)为空时,表消失。在以前的版本中,如果Shiny我相信表格会保持不变。
再现代码:
示例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
这看起来不错,但是如果您注意到按下Backspace时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)
}
)
我想要的行为:当按退格键清除菜单时,未触发watchEvents和eventReactive。
答案 0 :(得分:3)
似乎当前行为在退格键上触发了一个事件,但输入值保持不变。实际上,此行为可能是更新JavaScript函数Shiny.onInputChange
时发生的意外更改。 NEWS on shinys github site在版本1.1下主张以下权利。
新功能
[...]
对(未公开但广泛使用的)JavaScript函数
Shiny.onInputChange(name, value)
进行了两项更改。首先,我们将函数名称更改为Shiny.setInputValue
(但不用担心-旧的函数名称将继续起作用)。其次,直到现在,所有对Shiny.onInputChange(inputId, value)
的呼叫均已“重复数据删除”;也就是说,只要将输入设置为已经具有的相同值,该设置就会被忽略。使用Shiny v1.1,您现在可以添加一个options对象作为第三个参数:Shiny.setInputValue("name", value, {priority: "event"})
。将优先级选项设置为“事件”时,Shiny将始终发送该值并触发反应性,无论它是否重复。
当前版本的selectInput
似乎利用了这个新的{priority: "event"}
选项,但这只是猜测。
您可以通过对输入进行重复数据消除来调整服务器代码,以正确处理此新行为。
dedupedValue <- reactiveVal()
observe({ dedupedValue(input$value) })
然后,在其余的服务器代码中使用dedupedValue()
而不是input$value
。这也适用于旧版本的Shiny。
注意::如果您尝试在上面的代码中使用reactive
而不是observe
,则无法使用。
也许最好搁置此问题,直到有才华的开发人员查看your GitHub issue。如上所述,其原因可能是闪亮的JavaScript方面的接口更改。如果确实创建了代码突破性的更改,我相信开发人员将提供修复程序以确保向后兼容。
req
这基本上与当前问题无关,但提出了一个问题:如果您希望req
在条件不是“真实”的情况下重新训练旧输出,则应将其命名为
req(condition, cancelOuput = TRUE)