Reactivity in RShiny

RShiny uses a reactive programming coding pattern, which makes applications responsive. In reactive programming, there are basically three elements:

  • Reactive Source
  • Reactive Endpoint
  • Reactive Conductor

The combination of these elements is what makes a Shiny app more responsive. Let's have a look in more detail at how they work:

  • Reactive Source: The reactive source is the input objecting the Shiny app. It takes the input from the user and keeps it in the Input object. The Input object is associated with any UI element, with which the user interacts and provides input. It can be an input box, an action button, an interactive table or plot, or any other UI component. For example, if we take input from a text box named txtbox in the UI code, we can say that input$txtbox is the reactive source.
  • Reactive Endpoint: The reactive endpoint is the output object in a Shiny app. It accepts a value and puts that in the output components of the UI. The output components can be any UI element that is used to display the data in any format. The output object is output. For example, if we want to put the data into a plot named hist_plot in the UI file, then output$hist_plot will be the reactive endpoint.

A simple application can contain only these two elements: the source and the endpoint. Let's take a look at an example of an application that usually appears whenever we start a new Shiny application:

    library(shiny) 
    # Define UI for application that draws a histogram 
    ui<- fluidPage( 
       # Application title 
    titlePanel("Old Faithful Geyser Data"), 
       # Sidebar with a slider input for number of bins  
    sidebarLayout( 
    sidebarPanel( 
    sliderInput("bins", 
                         "Number of bins:", 
    min = 1, 
    max = 50, 
    value = 30) 
          ), 
    # Show a plot of the generated distribution 
    mainPanel( 
    plotOutput("distPlot") 
          ) 
       ) 
    ) 
    # Define server logic required to draw a histogram 
    server<- function(input, output) { 
    output$distPlot<- renderPlot({ 
          # generate bins based on input$bins from ui.R 
          x    <- faithful[, 2]  
    bins<- seq(min(x), max(x), length.out = input$bins + 1) 
          # draw the histogram with the specified number of bins 
    hist(x, breaks = bins, col = 'darkgray', border = 'white') 
       }) 
    } 
    # Run the application  
    shinyApp(ui = ui, server = server) 

You get the following output:

In the UI section of the preceding code, sliderInput is the input component named bins. In the server code section, input$bins is the reactive source. Similarly, plotOutput("distPlot") is the output component on the UI. As the value of input$bins changes, this plot also changes. This is how reactivity works. In the server section, output$distPlot is the reactive endpoint. This is represented here:

However, with more complex apps, the reactive source and endpoints can form different combinations. Imagine that a graph is to be built using two input values. In this case, the flow diagram would be as follows:

  • Reactive Conductor: So far, we have seen that the source is directly connected to the end point. There may be situations where there is a middle element between these two. This middle element is called a reactive conductor.

Reactive conductors are usually used to encapsulate slow operations or catch data. From Shiny's official website, https://shiny.rstudio.com/articles/reactivity-overview.html to calculate a number and inverse of it in the Fibonacci sequence for the nth element of a single application, which can be very time-consuming. This situation is shown in the code:

# Calculate nth number in Fibonacci sequence 
fib<- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) 
server<- function(input, output) { 
output$nthValue<- renderText({ fib(as.numeric(input$n)) }) 
output$nthValueInv<- renderText({ 1 / fib(as.numeric(input$n)) }) 
} 

The flow diagram would be as follows:

In such situations, a middle layer to catch the results can be added to reduce the time taken by this process. That is called a reactive conductor. The preceding code can be modified using a reactive conductor, as follows:

fib<- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) 
 
server<- function(input, output) { 
currentFib<- reactive({ fib(as.numeric(input$n)) }) 
 
output$nthValue<- renderText({ currentFib() }) 
output$nthValueInv<- renderText({ 1 / currentFib() }) 
} 
 

Now the flow diagram will look as follows:

Up until now, we have discussed three elements: the reactive source, the reactive conductor, and the reactive endpoints. These are the general terms used to describe reactive programming elements. In RShiny, the reactive source is known as the reactive value, the reactive endpoint is the observer, and the reactive conductor is the reactive expression. There are two fundamental differences between the observer and reactive conductor's functionality. The first is that the observer responds to event flushing but reactive expressions don't. The second is that reactive expressions can return values but the observer can't.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset