Reactives and Observers
In this section we discuss implementations of the three different types of reactive objects.
Reactive flow
As we go through the different implementations, I recommend that you think back to where they appear on the reactive flow chart.
Reactive inputs
An implementation of reactive inputs is reactiveValues()
.
One example is user inputs (input$*
). The input object is a reactive value that looks like a list, and contains many individual reactive values that are set by input from the web browser.
Reactive expressions
You can create reactive expressions with the reactive()
function.
An example is the reactive data frame subsets we created in the earlier sections and exercises.
Reactive expressions can access reactive values or other reactive expressions, and they return a value.
They are useful for caching the results of any procedure that happens in response to user input.
Implementation of reactive outputs
And lastly, the implementation for reactive outputs is observers.
For example, an output$*
object is a reactive observer. Actually, under the hood a render function returns a reactive expression, and when you assign this reactive expression to an output$*
value, Shiny automatically creates an observer that uses the reactive expression.
Observers can access reactive inputs and reactive expressions, but they don’t return a value.
Instead they are used for their side effects, which typically involves sending data to the web browser.
Reactives vs. observers
To help these concepts sink in a bit more, let’s compare reactives vs. observers.
Similarities
Both store expressions that can be executed
Differences
- Reactive expressions return values, but observers do not.
- Observers eagerly respond to reactives, but reactive expressions do not.
- Reactive expressions must not have side effects, while observers are only useful for their side effects.
Most importantly
- We use the
reactive()
function when calculating values, without side effects. - We use the
observe()
function when performing actions, with side effects. - The moral of the story is to not use
observe()
when calculating a value, and to especially not usereactive()
for performing actions with side effects.
Here is a summary table of the differences between reactives and observers.
reactive() |
observe() |
|
---|---|---|
Purpose | Calculations | Actions |
Side effects | Forbidden | Allowed |
A calculation is a block of code where you don’t care about whether the code actually executes—you just want the answer. Safe for caching. We use reactive()
for these.
An action is where you care very much that the code executes, and there is no return value, there are only side effects. For these we use observe()
.
Practice - Reactives vs. observers
Next you get to assess your understanding of reactives vs. observers.
You’ll add a reactiveValues()
element to the app. Define observers and their side effects, and how these compare to reactives.
Your turn
- Using the code from the app you worked on in the last exercise, add another
reactiveValues()
andreactiveVal()
element to the app.
Complete the exercise by building off of the code you completed in the last Posit Cloud Project titled 3-2b Find inconsistencies in what the app is reporting in your Posit Cloud Workspace