我正在制作一个 Rmarkdown
html_document
闪亮的应用程序,其中有一个 selectInput
。
我制作了一个最小的代码示例来重现我遇到的问题:
---
output: html_document
runtime: shiny
---
```{r echo=FALSE}
selectInput("selectYear", label = "Year", choices = c("All", 2006:2021), selected = "All")
observeEvent(input$selectYear, {
message("input$selectYear = ", input$selectYear)
throttle(
{
updateSelectInput(session, "selectYear", choices = c("All", 2006:2021), selected = input$selectYear)
},
100000
)
})
```<!-- -->
(您可以删除
<!-- -->
,这仅用于 SO 中的代码格式化。编辑:要运行它,我将其存储在 Rmd 文件中并使用 rmarkdown::run("filename.Rmd", shiny_args = list(port = 5050, host = "0.0.0.0"))
执行)
我还构建了几个图表(在这个最小的示例中进行了条纹化),并希望使用 JavaScript 触发
selectYear
的更改(例如,在单击图表中的条形图时)。这是重现该问题的片段:
Shiny.setInputValue('selectYear', 2015);
我遇到的问题是这个javascript触发了两倍的
observeEvent
,我们可以在日志中看到:
输入$selectYear = 2015
输入$selectYear = 2015
我知道在这个例子中这不是一个问题,因为它太快了,太引人注目了,但是当你有更多的数据处理代码并且应用程序中发生了许多事情时,这变得很明显,我的图表闪烁两次,间隔整秒,这是不可接受的.
请注意,如果您使用 html 下拉列表,则不会发生这种双重触发。
拥有
observeEvent
的原因是,如果我没有它,那么下拉列表不会以 2015
的新值在视觉上更新,该值仅在背景中发生变化,但 dom 不会改变。
因此,我设置了 observeEvent
和 updateSelectInput
来更改下拉列表的显示。我没有看到任何其他解决方案,但如果你有的话也可以在这里解决我的问题。
尝试过但失败了:
去抖/油门(如您在上面的代码片段中看到的)
从JS发送一个标志来防止双重触发:
Shiny.setInputValue('updateFromJS', true);
checkboxInput("updateFromJS", "updateFromJS", TRUE)
observeEvent(input$selectYear, {
message("input$selectYear = ", input$selectYear, " input$updateFromJS = ", input$updateFromJS)
if (input$updateFromJS == TRUE) {
message("updating...")
updateCheckboxInput(session, "updateFromJS", "updateFromJS", FALSE) ## i.e. input$updateFromJS <- FALSE
updateSelectInput(session, "selectYear", choices = c("All", 2006:2021), selected = input$selectYear)
}
})
我还想知道为什么它运行两次而不是无限循环。 为什么
throttle
和 debounce
不起作用?
当您运行
Shiny.setInputValue("selectYear", 2015)
时,input$selectYear
会获取值 2015
,即一个 number。然后 updateSelectInput
将 input$selectYear
设置为值 "2015"
,即字符串。不存在无限循环,因为之后没有任何变化input$selectYear
。
要看到:
observeEvent(input$selectYear, {
message("input$selectYear = ", mode(input$selectYear))
updateSelectInput(session, "selectYear", selected = input$selectYear)
})