Shiny: Differencebetween Observeevent and Eventreactive

Shiny: what is the difference between observeEvent and eventReactive?

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

R shiny: different behaviours of observeEvent and eventReactive

It's because edits() isn't called thereafter, so shiny thinks you don't need it, hence no reason to do any work on it, you need to add where it should go or what you want to do with it:

library(shiny)

ui <- fluidPage(
rhandsontable::rHandsontableOutput(
outputId = "data")
)

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

data <- data.frame(a = 1, b = 2, c = 3)

output$data <- rhandsontable::renderRHandsontable({
rhandsontable::rhandsontable(
selectCallback = TRUE,
data = data)
})

observeEvent(input$data$changes$changes, {
print("ping")
})

edits <- eventReactive(input$data$changes$changes, {
print("pong")
})

observe({
edits()
})

}

shinyApp(ui = ui, server = server)

Advantages of reactive vs. observe vs. observeEvent

First off this stuff is sort of ambiguous, and not very intuitive in some ways, it even says so on the Shiny blog!

Here is my best understanding of the topic..

Lets start with reactive

The reactive function allows a user to monitor the status of an input or other changing variable and return the value to be used elsewhere in the code. The monitoring of a reactive variable is considered lazy, "Reactive expressions use lazy evaluation; that is, when their dependencies change, they don't re-execute right away but rather wait until they are called by someone else.(Source)". You show this well in example 2, as you can call the variable inside the renderText environment, once called the code inside the reactive call executes and re-evaluates the variable.

For science nerds, this is a lot like quantum mechanics in that by calling the reactive variable (observing it) causes it to change by re-evaluating, too much of a stretch?

Now to observe

Observe is similar reactive, the main difference is that it does not return any values to any other environment besides its own, and it is not lazy. The observe function continually monitors any changes in all reactive values within its environment and runs the code in it's environment when these values are changed. So, observe is not a "lazy" evaluation since it does not wait to be called before it re-evaluates. Again note that you cannot assign variables from observe.

For sake of experiment:

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

observe({
if (input$choice == 'Hello') {
getStatus <- 'Hi there'
}
})

observe({
if (input$choice == 'Goodbye') {
getStatus <- 'See you later'
}
})

output$result <- renderText({
getStatus
})

})

shinyApp(ui = ui, server = server)

Sample Image

What is important to notice is that during the code executed in observe, we can manipulate outside environment reactive variables. In your case you assign text <- reactiveValues() and then manipulate that by calling text$result <- 'Hi there'. We can also do things like update selectInput choices, or other shiny widgets, but we cannot assign any non-reactive variables in this environment like our getStatus in the example above. And this idea is mentioned on the observe documentation,

"An observer is like a reactive expression in that it can read reactive values and call reactive expressions, and will automatically re-execute when those dependencies change. But unlike reactive expressions, it doesn't yield a result and can't be used as an input to other reactive expressions. Thus, observers are only useful for their side effects (for example, performing I/O)(Source)"

Lastly, observeEvent

The best way to use observeEvent is to think of it as a defined trigger, as in it watches one event or change in a variable, and then fires when the event happens. I most commonly use this to watch input to buttons, as that is a defined event in which I want things to happen after the button is pushed. It uses an isolate environment which I think is the perfect name for how this function works.

Inside this environment we can call a bunch of reactive variables, but we only define one as the trigger. The main difference between observeEvent and observe being the trigger, as observe runs anytime anything changes, and observeEvent waits for the trigger. Note that this environment is similar to observe in that it does not return non-reactive variables.

Summary

Here is an example that brings all these ideas together:

library(shiny)

ui<-
fluidPage(
fluidRow(
column(4,
h2("Reactive Test"),
textInput("Test_R","Test_R"),
textInput("Test_R2","Test_R2"),
textInput("Test_R3","Test_R3"),
tableOutput("React_Out")
),
column(4,
h2("Observe Test"),
textInput("Test","Test"),
textInput("Test2","Test2"),
textInput("Test3","Test3"),
tableOutput("Observe_Out")
),
column(4,
h2("Observe Event Test"),
textInput("Test_OE","Test_OE"),
textInput("Test_OE2","Test_OE2"),
textInput("Test_OE3","Test_OE3"),
tableOutput("Observe_Out_E"),
actionButton("Go","Test")
)

),
fluidRow(
column(8,
h4("Note that observe and reactive work very much the same on the surface,
it is when we get into the server where we see the differences, and how those
can be exploited for diffrent uses.")
))

)

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

# Create a reactive Evironment. Note that we can call the varaible outside same place
# where it was created by calling Reactive_Var(). When the varaible is called by
# renderTable is when it is evaluated. No real diffrence on the surface, all in the server.

Reactive_Var<-reactive({c(input$Test_R, input$Test_R2, input$Test_R3)})

output$React_Out<-renderTable({
Reactive_Var()
})

# Create an observe Evironment. Note that we cannot access the created "df" outside
# of the env. A, B,and C will update with any input into any of the three Text Feilds.
observe({
A<-input$Test
B<-input$Test2
C<-input$Test3
df<-c(A,B,C)
output$Observe_Out<-renderTable({df})
})

#We can change any input as much as we want, but the code wont run until the trigger
# input$Go is pressed.
observeEvent(input$Go, {
A<-input$Test_OE
B<-input$Test_OE2
C<-input$Test_OE3
df<-c(A,B,C)
output$Observe_Out_E<-renderTable({df})
})

}
shinyApp(ui, server)

reactive
Create a variable that can be changed over time by user inputs, evaluates "lazy" meaning only when called.

observe
Continually monitor reactive events and variables, whenever ANY reactive variable is changed in the environment (the observed environment), the code is evaluated. Can change values of previously defined reactive variables, cannot create/return variables.

observeEvent (Domino Effect)
Continually monitor ONE defined reactive variable/event (the trigger) and run the code when the the trigger is activated by change/input of that trigger. Can change values of previously defined reactive variables, cannot create/return variables.

eventReactive Create a variable, with a defined trigger similar to observeEvent. Use this when you want a reactive variable that evaluates due to a trigger instead of when it is called.

I hope this helps, and if I am mistaken in my understanding or there could be more clarification, feel free to edit this answer.

R Shiny: eventReactive/ObserveEvent, eventExpr has AND

My answer comes from this thread: Shiny R observeEvent with Multiple Conditions from selectInput and I wanted to make it visible here as well, because it worked well for me.

In your case the fix would probably be

observeEvent(req(input$selectInput1, input$actionButton), {
updateSelectInput(session = session, inputId = "input2", label = "b", choices = input$selectInput1, selected = input$selectInput1)
})

Can't update inputs in shiny app with observeEvent and eventReactive

Try this

# Options for tabs

años <- c("2019", "2020", "2021")

meses <- c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Juno", "Julio",
"Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")

opciones <- c("L1","L2","L3","LA","LB","LC")

lugar <- list(L1=c("EXT","INT","LOC"), L2=c("NOM","KHA","POC"),
L3= c("TMO", "MCR", "GNR"), LA=c("APV", "HOT", "ROR"),
LB= c("GRU", "BOY", "POK"), LC=c("NOT", "LOX", "TAK"))

## App

test_lugar <- tabPanel(
titlePanel= "Test",
titlePanel(h5("Test")),
sidebarLayout(
sidebarPanel(
selectInput("año", "Año", choices=años,
selected= "2019"),
selectInput("mes", "Mes", choices=meses,
selected="Enero", multiple=TRUE),
selectInput("opcion", "Opción",
choices=opciones, selected="L1"),
selectInput("lugar", "Lugar", c(), multiple=TRUE)
),
mainPanel(
#plotlyOutput("afluencia_estaciones", height = "400px", width="1000px")
)
)
)


ui <- navbarPage(title = h5(strong("XXXX")),
theme = shinytheme("paper"),
test_lugar)

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

seleccionar_opcion_lugar <- eventReactive(input$opcion, {
get("lugar")[[input$opcion]]
})

observe({print(seleccionar_opcion_lugar())})

#lugar_seleccionado <-
observeEvent(input$opcion, {
req(seleccionar_opcion_lugar())
choices <- unlist(seleccionar_opcion_lugar())
updateSelectInput(session,"lugar", choices=choices,
selected=choices[1])
}, ignoreNULL = FALSE)

# Then some barplot here

}

shinyApp(ui, server, options = list(launch.browser = TRUE))

output

Output of observeEvent() in R Shiny

You almost have the correct answer. If you look at the entry for observeEvent() in the Shiny reference documentation, you will see that there is another function on the same page: eventReactive(). They work almost the same way, but eventReactive() returns a reactive object. So, to make your code work the way you want it to work, all you need to do is change your

observeEvent(input$chg_class, {
...
})

to

modified_df1 <- eventReactive(input$chg_class, {
...
})


Related Topics



Leave a reply



Submit