Observe Function in R Shiny – How to Implement a Reactive Observer


It’s easy to get down the basics of R and Shiny, but the learning curve becomes significantly steeper after a point. Reactive values? Reactive events? Reactive observers? Let’s face it – it’s easy to get lost. We’re here to help.

Today you’ll learn all about the Observe function in R Shiny – what it is, what it does, and how to use it in practice with two hands-on examples. We’ll kick things off with a bit of theory, just so you can understand why reactive observers are useful.

Do you need help with your enterprise Shiny app? Reach out to the Shiny experts.

Table of contents:


What is Observe Function in R Shiny / Reactive Observer

The expression passed into the observe() function is triggered every time one of the inputs changes. If you remember only a single sentence from this article, that should be the one.

So, what makes the observe() function different from regular reactive expressions? Well, observe() yields no output and can’t be used as an input to other reactive expressions. Reactive observers are only useful for their “side effects”, such as I/O, triggering a pop-up, and so on.

Is your R Shiny app ready for deployment? Here are 3 ways to share R Shiny apps.

As mentioned before, observers re-execute as soon as their dependencies change, making them use a concept known as eager evaluation. On the other end, reactive expressions are lazy-evaluated, meaning they have to be called by someone else to re-execute.

You can check all the parameters the observe() function can accept in the official documentation, but we won’t go over that here. Instead, we’ll dive into two hands-on examples.

Example 1 – Basic Demonstration of the Observe Function in R Shiny

To demonstrate how the Observe function in R Shiny works, we’ll do something you’d never do in a real life. But there’s a good reason why we’re doing it. It perfectly demonstrates what the observe() function does, and how a reactive observer works.

We already mentioned that the function is triggered every time one of the inputs changes. So, we can declare input and attach it to an observer to monitor what happens as we mess around with it.

That’s exactly what the code snippet below does. There are two UI elements – sliderInput and textOutput. Inside the server() function, we have attached a reactive observer to the sliderInput, and each time it changes, we update the text contents of the textOutput.

There are easier and more intuitive ways to implement the same behavior, but you get the gist – each time the input changes we trigger some code. It’s irrelevant which code we trigger, but in this case, the code just changes the text:

library(shiny)

ui <- fluidPage(
    sliderInput(inputId = "slider", label = "Select a number:", min = 1, max = 100, value = 10, step = 1),
    textOutput(outputId = "result")
)

server <- function(input, output) {
    observe({
        input$slider
        output$result <- renderText({
            input$slider
        })
    })
}

shinyApp(ui = ui, server = server)

Below you’ll find a GIF demonstrating how the R Shiny app works:

Image 1 – Basic example of an R Shiny reactive observer

That was easy, right? Next, we’ll go over a slightly more complicated example.

Example 2 – Using a Reactive Observer to Update Dropdown Choices

All dashboards have dropdown menus, or select inputs, as R Shiny calls them. The premise is simple – you select a value, and then charts/tables on a dashboard are re-drawn.

But how can you introduce dependencies between dropdown menus? In other words, how can you base what’s shown as options for the second dropdown menu based on the value selected from the first menu?

That’s where the Observe function in R Shiny comes in.

If you want to follow along, copy the following dataset and save it as data.csv:

"x","y"
"A","A1"
"A","A2"
"A","A3"
"A","A4"
"A","A5"
"B","B1"
"B","B2"
"B","B3"
"B","B4"
"B","B5"
"C","C1"
"C","C2"
"C","C3"
"C","C4"
"C","C5"

The example Shiny dashboard below will read the dataset and declare two selectInput‘s in the UI. The second depends on the first. For example, if the user selects “A” in the first dropdown menu, only options of “A1” to “A5” should be shown in the second menu. The same thing goes for the other letters.

Need help from a Shiny consultant? See how RStudio (Posit) Certified Partners can help you and your team.

Inside the server() function, we’ll use the dplyr package to filter out the records we don’t need, and then use the updateSelectInput() function to “re-write” the choices for the second dropdown menu.

That’s it! Let’s see the code:

library(shiny)
library(dplyr)

dummy_data <- read.csv("data.csv")

ui <- fluidPage(
    selectInput(inputId = "col_x", label = "X:", choices = dummy_data$x, selected = dummy_data$x[1]),
    selectInput(inputId = "col_y", label = "Y:", choices = dummy_data$y, selected = dummy_data$y[1])
)

server <- function(input, output, session) {
    observe({
        y_vals <- dummy_data %>% filter(x == input$col_x) %>% select(y)
        
        updateSelectInput(
            session = session, 
            inputId = "col_y",
            choices = y_vals,
            selected = head(y_vals, 1)
        )
    })
}

shinyApp(ui = ui, server = server)

Below is a GIF showing you how the app works:

Image 2 – Updating dropdown menu options with the Observe function

Works like a charm. Let’s make a short recap and go over the homework assignment.


Summary of a Reactive Observer in R Shiny

Today you’ve learned the basics of the Observe function in R Shiny (reactive observer) both through theory and practical examples. The moral of the story is as follows – use the observe() function every time you want your Shiny app to react to a change of the input. Common examples are conditionally rendered UI elements, such as options of a dropdown menu.

For a homework assignment, we encourage you to explore the reactive observer further on your own. You could try working with radio buttons, and conditionally change the values of a subsequent group based on what the user previously selected. Give it a go, and make sure to share your results with us on Twitter – @appsilon. We’d love to see what you come up with.

Looking to migrate your RStudio workflow to cloud? Here’s how you can get started for free.