This question is related to this one. The two can generate the same functionality, but implementation is slightly different. One significant difference is that a reactiveValue
is a container that can have several values, like input$
. In shiny documentation functionality is usually implemented using reactive()
, but in most cases I find reactiveValues()
more convenient. Is there any catch here? Are there any other major differences between the two that I might not be aware off? Are these two code snippets equivalent?
See the same example code implemented using:
a reactive expression:
library(shiny) ui <- fluidPage( shiny::numericInput(inputId = 'n',label = 'n',value = 2), shiny::textOutput('nthValue'), shiny::textOutput('nthValueInv') ) fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) server<-shinyServer(function(input, output, session) { currentFib <- reactive({ fib(as.numeric(input$n)) }) output$nthValue <- renderText({ currentFib() }) output$nthValueInv <- renderText({ 1 / currentFib() }) }) shinyApp(ui = ui, server = server)
a reactive value:
library(shiny) ui <- fluidPage( shiny::numericInput(inputId = 'n',label = 'n',value = 2), shiny::textOutput('nthValue'), shiny::textOutput('nthValueInv') ) fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) server<-shinyServer(function(input, output, session) { myReactives <- reactiveValues() observe( myReactives$currentFib <- fib(as.numeric(input$n)) ) output$nthValue <- renderText({ myReactives$currentFib }) output$nthValueInv <- renderText({ 1 / myReactives$currentFib }) }) shinyApp(ui = ui, server = server)
Reactive values contain values (not surprisingly), which can be read by other reactive objects. The input object is a ReactiveValues object, which looks something like a list, and it contains many individual reactive values. The values in input are set by input from the web browser.
observe and observeEvent are similar to reactive expressions. The big difference is that the observers do not yield any output and thus they are only useful for their side effects.
They are identical but for one thing: observeEvent() just executes code within it's boundaries but does not assign the output to anything. eventReactive() will save the output to a reactive variable.
Description. The reactiveVal function is used to construct a "reactive value" object. This is an object used for reading and writing a value, like a variable, but with special capabilities for reactive programming.
There is a catch, though it won't come into play in your example.
The shiny developers designed reactive()
to be lazy, meaning that the expression contained in it will only be executed when it is called by one of its dependents. When one of its reactive dependencies is changed, it clears its cache and notifies its own dependents, but it is not itself executed until asked to by one of those dependents. (So if, say, its sole dependent is a textOutput()
element on a hidden tab, it won't actually be executed unless and until that tab is opened.)
observe()
, on the other hand, is eager; the expression that it contains will be executed right away whenever one of its reactive dependencies is changed -- even if it's value is not needed by any of its dependents (and in fact even if has no dependents). Such eagerness is desirable when you're calling observe()
for its side-effects, but it can be wasteful when you're only using it to pass on the return value of its contents to other reactive expressions or endpoints down the line.
Joe Cheng explains this distinction quite well in his 2016 Shiny Developer Conference presentation on "Effective reactive programming", available here. See especially the bit starting around 30:20 in the presentation's second hour. If you watch until 40:42 (blink and you'll miss it!) he briefly characterizes the behavior of the observe()
/reactiveValue ()
combination that you like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With