Shiny: 观察事件和事件反应之间的区别是什么?

我现在已经读了好几遍 Shiny 关于响应式编程的文档,但是我还是不能很好地理解 observeEventeventReactive之间的区别。

文件上说:

无论何时您希望执行响应事件的操作,都可以使用观察事件。(注意,“重新计算一个值”通常不算执行一个操作——请参阅 eventReactive。)

....

使用 eventReactive 创建一个计算值,该值仅在响应事件时更新。这就像一个正常的反应表达式,只不过它忽略了所有来自其反应依赖性的常见失效;

在我尝试的所有情况中,我看不出使用 observeEventeventReactive有什么不同(不管我使用什么函数,代码都能正常工作,对性能没有明显影响)。

你能帮我弄清楚这两者之间的真正区别吗?理想情况下,我希望一些例子,显示当他们是可互换的,一个当 observeEvent将工作,但不是 eventReactive,反之亦然。

79416 次浏览

It's like the difference between observe and reactive. One is intended to be run when some reactive variable is "triggered" and is meant to have side effects (observeEvent), and the other returns a reactive value and is meant to be used as a variable (eventReactive). Even in the documentation for those functions, the former is shown without being assigned to a variable (because it is intended to just produce a side effect), and the latter is shown to be assigned into a variable and used later on.

As @daatali is saying the two functions are used for different purposes.

ui <- shinyUI(pageWithSidebar(
headerPanel("eventReactive and observeEvent"),
sidebarPanel(
actionButton("evReactiveButton", "eventReactive"),
br(),
actionButton("obsEventButton", "observeEvent"),
br(),
actionButton("evReactiveButton2", "eventReactive2")
),
mainPanel(
verbatimTextOutput("eText"),
verbatimTextOutput("oText")
)
))


server <- shinyServer(function(input, output) {
etext <- eventReactive(input$evReactiveButton, {
runif(1)
})
observeEvent(input$obsEventButton,{
output$oText <- renderText({ runif(1) })
})
eventReactive(input$evReactiveButton2,{
print("Will not print")
output$oText <- renderText({ runif(1) })
})
output$eText <- renderText({
etext()
})
})


shinyApp(ui=ui,server=server)

eventReactive creates a reactive value that changes based on the eventExpr while observeEvent simply is triggered based on eventExpr

I think the top level practical aspects need to be emphasized here.

  • An eventReactive creates an object that you define like reactive does, but with out usual chain-reaction behavior you get from reactive. However it is lazily evaluated and cached like the other reactives.

  • An observeEvent can not create an object that you define (it creates something else). It is immediately evaluated and not cached. It is for causing side-effects.

So if you need a data frame, or vector, or plot or something, but want to decouple from the usual reactive chain-reactions, use eventReactive.

If you just want to cause an immediate side effect, observeEvent is your ticket.

Providing the way I understand this , correct me and add more information as required . Most of the information is from https://shiny.rstudio.com/articles/action-buttons.html

  • Also may be this has been asked long ago, I had the same question while going through eventReactive() and observeEvent()
  • ObeserveEvent , being more like a trigger for an event while eventReactive , being more like a delay
  • Below I try the same code , using both the reactive functions

To build several action buttons that control the same object, combine observeEvent() calls with reactiveValues() , Here I can use two actionButtons which are working at the same time in the same code.

Code.1 Gives the effect of observeElement()

Code.2 Uses eventReactive() , but if I try to use two different actionButtons, only the latest one works the earlier button is null and did not react

  • Code 1

        library(shiny)
    
    
    ui<-fluidPage(
    actionButton("runif", "uniform"),
    actionButton("rnorm", "Normal"),
    hr(),
    plotOutput("plot")
    )
    
    
    server<-function(input, output){
    v<-reactiveValues(data=NULL)
    
    
    observeEvent(
    input$runif,
    {
    v$data<-runif(100)
    }
    )
    
    
    observeEvent(
    input$rnorm,
    {
    v$data<-rnorm(100)
    }
    )
    
    
    output$plot <- renderPlot(
    {
    if (is.null(v$data)) return()
    hist(v$data)
    }
    )
    }
    
    
    shinyApp(ui, server)
    
  • code2

       library(shiny)
    
    
    ui<-fluidPage(
    actionButton(inputId = "norm", label = "Normal"),
    actionButton(inputId = "unif", label = "Uniform"),
    
    
    #Normal
    plotOutput("hist")
    )
    
    
    server <- function(input, output) {
    
    
    dnorm <- eventReactive(input$norm, {rnorm(100)})
    dunif <- eventReactive(input$unif, {runif(100)})
    
    
    output$hist <- renderPlot({
    hist(dfnorm())
    })
    
    
    output$hist <- renderPlot({
    hist(dunif())
    })
    }
    
    
    shinyApp(ui, server)
    

I found this helpful for understanding eventReactive:

eventReactives are similar to reactives, they are constructed as follows:

eventReactive( event {
code to run
})

eventReactives are not dependent on all reactive expressions in their body ('code to run' in the snippet above). Instead, they are only dependent on the expressions specified in the event section.