6

Let's say I have the following UI:

ui <- fluidPage(
checkboxGroupInput("checkbox", "", choices = colnames(mtcars)),
tableOutput("table")
)

I want to render a table of mtcars once at least one checkbox option has been selected. For this, I came across req(), but I can't see how is it different from an if statement, even reading the documentation about this function, it's definition is very close to what an if statement does:

Ensure that values are available ("truthy"–see Details) before proceeding with a calculation or action. If any of the given values is not truthy, the operation is stopped by raising a "silent" exception (not logged by Shiny, nor displayed in the Shiny app's UI).

So, how is this table rendering:

server <- function(input, output) {

    output$table <- renderTable({
    req(input$checkbox)
    mtcars %>% select(input$checkbox)
    })
}

shinyApp(ui, server)

different from this one?:

server <- function(input, output) {

    output$table <- renderTable({
    if(!is.null(input$checkbox))
    mtcars %>% select(input$checkbox)
    })
}

shinyApp(ui, server)

TL;DR: how is req() different from an if statement other than how you write it?

David Jorquera
  • 2,046
  • 12
  • 35

1 Answers1

10

Well, you can see the code for req by typing its name without the parenthesis.

function (..., cancelOutput = FALSE) 
{
    dotloop(function(item) {
        if (!isTruthy(item)) {
            if (isTRUE(cancelOutput)) {
                cancelOutput()
            }
            else {
                reactiveStop(class = "validation")
            }
        }
    }, ...)
    if (!missing(..1)) 
        ..1
    else invisible()
}

What's basically happening is that it loops over all the values you pass in and checks if they look "truthy" rather than just checking for null. And if so, it will cancel the output. And if statement will only conditionally execute a block of code, it will not cancel the output necessarily. When you have this block for example

server <- function(input, output) {
    output$table <- renderTable({
      if(!is.null(input$checkbox)) 
         mtcars %>% select(input$checkbox)
      print("ran")
    })
}

The code inside the if expression is conditioanally run, but The print() after is still always run because it's not in the if block. But with a req

server <- function(input, output) {
    output$table <- renderTable({
      req(input$checkbox)
      mtcars %>% select(input$checkbox)
      print("ran")
    })
}

The req() basically aborts the rest of the block so the print() doesn't run if the req is not a "truthy" value. It just makes it easier to prevent unnecessary code from running.

MrFlick
  • 195,160
  • 17
  • 277
  • 295