I have been programming Shiny applications for several years. One of the things I was taught already from the start was to never use render*()
functions inside observe()
or observeEvent()
. This makes sense because the output created by the render function is already reactive, and I have kept this as a core principle whenever writing Shiny code. All output$... <- render*(...
calls are placed directly in the server function. However, I did never really think much about why or why not it would be bad practice to nest render functions inside observers.
As it happens, I have now come across an existing Shiny application that has essentially all its render calls inside observers, typically something like this:
observeEvent(input$foo, {
if (input$foo == "Case 1") {
output$bar <- renderPlot({
# Code to generate plot for case 1
})
}
else if (input$foo == "Case 2") {
output$bar <- renderPlot({
# Code to generate plot for case 2
})
}
})
instead of the way I would have written it, i.e. something like:
output$bar <- renderPlot({
if (input$foo == "Case 1") {
# Code to generate plot for case 1
}
else if (input$foo == "Case 2") {
# Code to generate plot for case 2
}
})
However, the app seems to be working exactly as intended, which made me wonder what really is going on here. Reading various threads on Stack Overflow and other places led me to a few comments indicating that it is indeed bad practice to place render function calls inside observers, but they offered very little explanation. Is there anyone out there with good knowledge about the fundamentals of Shiny that can expand on these questions:
- Is it bad practice to place render function calls inside observers, or is this simply a myth?
- If it is bad, what specifically are the issues, and why?
Any help would be greatly appreciated!