在Rshiny中,为什么javascript函数setInputValue会让observeEvent运行两次?

问题描述 投票:0回答:1

我正在制作一个 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
不起作用?

javascript r shiny r-markdown
1个回答
0
投票

当您运行

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)
  })
© www.soinside.com 2019 - 2024. All rights reserved.