colinfang colinfang - 1 year ago 49
R Question

What's the difference between Reactive Value and Reactive Expression?

In Shiny tutorial, there is an example:

fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))

shinyServer(function(input, output) {
currentFib <- reactive({ fib(as.numeric(input$n)) })

output$nthValue <- renderText({ currentFib() })
output$nthValueInv <- renderText({ 1 / currentFib() })

I don't get how
caches the values. Does it internally do something like
return(function() cachedValue)
Now I am wondering if I can do this?

fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))

shinyServer(function(input, output) {
currentFib <- reactiveValues({ fib(as.numeric(input$n)) })

output$nthValue <- renderText({ currentFib })
output$nthValueInv <- renderText({ 1 / currentFib })

Answer Source

Using currentFib <- reactiveValues({ fib(as.numeric(input$n)) }) will not work in this context. You will get an error saying that you are accessing reactive values outside of the "reactive context."

However, if you wrap it inside a function call instead, it will work:

currentFib <- function(){ fib(as.numeric(input$n)) }

This works because now the function call is inside a reactive context.

The key difference is the distinction they make in the Shiny documentation, between reactive "sources" and "conductors." In that terminology, reactive({...}) is a conductor, but reactiveValues can only be a source.

  • Here's how I think of reactiveValues - as a way to extend input which gets specified in UI.R. Sometimes, the slots in input are not enough, and we want derived values based on those input slots. In other words, it is a way to extend the list of input slots for future reactive computations.

  • Reactive() does what you say -- it returns the value, after re-running the expression each time any reactive Value changes. If you look at the source code for reactive you can see it: The last line is that cached value that is being returned: Observable$new(fun, label)$getValue where 'fun' is the expression that was sent in the call to reactive.