首页 > 解决方案 > shiny::observeEvent 工作或中断的条件是什么,即隔离其参数

问题描述

在我的理解中,observeEvent将 in 中的所有内容都handlerExpr视为包装在一个isolate函数中,因此它应该只在输入或reactiveValueineventExpr无效(更改)时触发(这里完全不是解释@divibisan)。

在这个带有操作按钮的闪亮应用程序中,这有时有效,有时无效。有人可以解释一下,为什么会这样。(部分代码取自RStudio 网站,假设我可以这样做。

当按下Go按钮时,此应用程序将绘制两个相同的所选国家人口的条形图。我的经验是,在第一次按下Go按钮后,两个图表都会被渲染。更进一步,上图将立即更新,忽略按钮(# case 1 - 操作按钮损坏),而第二个图仅按预期更新按钮事件(# case 2 - 仅在按下 Go 按钮时操作)。

  1. 你能重现这种行为吗?
  2. 为什么会这样,规则是什么?
  3. 我好像不明白。

.

library(shiny)
library(DBI)
library(pool)
library(dplyr)
library(dbplyr)
library(forcats)
library(ggplot2)

pool <- dbPool(
  drv = RMySQL::MySQL(),
  dbname = "shinydemo",
  host = "shiny-demo.csa7qlmguqrf.us-east-1.rds.amazonaws.com",
  username = "guest",
  password = "guest"
)

query <- function(inp){
  pool %>%
    tbl("Country") %>%
    select(Code,Name) %>%
    rename(CountryName = Name) %>%
    filter(CountryName == !!inp) %>%
    left_join(.,pool %>%
                tbl("City"),by = c("Code" ="CountryCode")) %>%
    select(CountryName, Name,Population) %>% arrange(desc(Population)) %>%
    collect()
}

gplot <- function(x){
  ggplot2::ggplot(x %>% mutate(Name = fct_reorder(Name,Population,.desc=TRUE)),aes(x=Name,y=Population)) + 
  geom_bar(stat="identity") +     
  theme(axis.text.x = element_text(angle = 90)) 
}

ui <- fluidPage(
  selectInput("selectcountry", label = h3(""), 
              choices = as.list( pool %>% tbl("Country") %>% pull(Name))),
  actionButton("do", label ="Go" ),
  htmlOutput("actionbuttoncounter"),
  plotOutput("popPlot"),
  plotOutput("popPlot2")
)

server <- function(input, output, session) {
  session$onSessionEnded(function(){pool::poolClose(pool)})

  output$actionbuttoncounter <- renderText(input$do)
  observeEvent(input$do, {

    # case 1 - action button broken
    output$popPlot <- renderPlot({
      query(inp = input$selectcountry) %>% gplot()
    })
    # case 2 - action only when Go-button is pressed
     result <- query(inp = input$selectcountry)
     output$popPlot2<- renderPlot({
       gplot(result)
     })
  })
}
shinyApp(ui, server)

更新

这与 dbplyr 无关,所以一个最小的例子是:

library(shiny)
library(dplyr)
gplot <- function(x){
  hist(x)
}

ui <- fluidPage(
  numericInput("num", label = h3("Numeric input"), value = 1),
  actionButton("do", label ="Go" ),
  htmlOutput("actionbuttoncounter"),
  plotOutput("popPlot"),
  plotOutput("popPlot2")
)

server <- function(input, output, session) {


  output$actionbuttoncounter <- renderText(input$do)
  observeEvent(input$do, {
    # case 1 - action button broken
    output$popPlot <- renderPlot({
      rnorm(input$num) %>% gplot()
    })
    # case 2 - propper action
    result <- rnorm(input$num)
    output$popPlot2<- renderPlot({
     result %>% gplot()
    })
  })
}
shinyApp(ui, server)

附加信息

R version 3.6.0 (2019-04-26)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.6

locale:
[1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8

other attached packages:
[1] ggplot2_3.2.0 forcats_0.4.0 dbplyr_1.4.2  dplyr_0.8.3   pool_0.1.4.2  DBI_1.1.0     shiny_1.4.0  

标签: rshiny

解决方案


同意@user5249203。建议不要包括output从内部渲染observeEvent(这不需要工作)。

这是reactive每次按下按钮时更新值的一种方法。当数据发生变化时,图表将自动更新。

这是否具有您正在寻找的行为?

server <- function(input, output, session) {

  rv <- reactiveVal()

  output$actionbuttoncounter <- renderText(input$do)

  observeEvent(input$do, {
    rv(rnorm(input$num))
  })

  output$popPlot <- renderPlot({
    if (is.null(rv())) return ()
    gplot(rv())
  })

  output$popPlot2 <- renderPlot({
    if (is.null(rv())) return ()
    gplot(rv())
  })

}

推荐阅读