reactive() and render...()?

33 views
Skip to first unread message

3D0G

unread,
Oct 26, 2016, 8:44:02 PM10/26/16
to Shiny - Web Framework for R
Yesterday I watched Joe Cheng's videos from the 2016 Shiny developer conference (https://www.rstudio.com/resources/webinars/shiny-developer-conference/). I don't think I understood reactivity at all until I watched his two videos.

Today I've been playing with what I learned. But I don't understand why he didn't say something like "all the render... commands also create reactive expressions." Maybe I missed it? Maybe I misunderstand render functions?

Are there other commands that create reactive expressions besides reactive() and the render...() group?


Joe Cheng

unread,
Oct 27, 2016, 6:30:29 PM10/27/16
to 3D0G, Shiny - Web Framework for R
You can think of renderXXX({...}) as creating a reactive expression. That is probably the most useful way to think about things.

But as a matter of implementation, it's not actually true. It just so happens that outputs are implemented using observers, and renderXXX only needs to return a function, that will be called from within that observer. (Very early versions of Shiny actually called these reactiveXXX, as in output$plot <- reactivePlot(...).)

I can prove it:

> is.reactive(renderText("hi"))
[1] FALSE
> is.function(renderText("hi"))
[1] TRUE

So this actually works, though we don't recommend this syntax:

output$foo <- function() {
  input$x
}

This works too and is (I think) more readable, hence recommended, but isn't technically necessary:

output$foo <- reactive({
  input$x
})

In a way, outputs/renderXXX are really their own thing. They're similar to reactive expressions except that you can't use them in other reactive expressions or other outputs (i.e. they don't compose). And they're similar to observers except that you don't actually do side-effecty things inside of them.

Inside of Shiny there's a method called defineOutput, and output$x<-y is actually a call to defineOutput(x, y). It looks essentially like this (OK not really but this gives you the basic idea):

defineOutput <- function(name, renderFunc) {
  observe({
    value <- renderFunc()
    browser$updateOutput(name, value)
  })
}

So the renderXXX functions take a code chunk, and return a function that is used as the "renderFunc" in the code snippet above.

--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/shiny-discuss/84e29862-7c26-49de-b92e-67b723992266%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dean Attali

unread,
Oct 28, 2016, 2:53:10 PM10/28/16
to Shiny - Web Framework for R, tom.we...@gmail.com
Thanks for the very detailed answer Joe, I learned a lot from it 
Reply all
Reply to author
Forward
0 new messages