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).
req(..., cancelOutput = FALSE) isTruthy(x)
... | Values to check for truthiness. |
---|---|
cancelOutput | If |
x | An expression whose truthiness value we want to determine |
The first value that was passed in.
The req
function was designed to be used in one of two ways. The first
is to call it like a statement (ignoring its return value) before attempting
operations using the required values:
rv <- reactiveValues(state = FALSE) r <- reactive({ req(input$a, input$b, rv$state) # Code that uses input$a, input$b, and/or rv$state... })
In this example, if r()
is called and any of input$a
,
input$b
, and rv$state
are NULL
, FALSE
, ""
,
etc., then the req
call will trigger an error that propagates all the
way up to whatever render block or observer is executing.
The second is to use it to wrap an expression that must be truthy:
output$plot <- renderPlot({ if (req(input$plotType) == "histogram") { hist(dataset()) } else if (input$plotType == "scatter") { qplot(dataset(), aes(x = x, y = y)) } })
In this example, req(input$plotType)
first checks that
input$plotType
is truthy, and if so, returns it. This is a convenient
way to check for a value "inline" with its first use.
Truthy and falsy values
The terms "truthy" and "falsy" generally indicate whether a value, when
coerced to a base::logical()
, is TRUE
or FALSE
. We use
the term a little loosely here; our usage tries to match the intuitive
notions of "Is this value missing or available?", or "Has the user provided
an answer?", or in the case of action buttons, "Has the button been
clicked?".
For example, a textInput
that has not been filled out by the user has
a value of ""
, so that is considered a falsy value.
To be precise, req
considers a value truthy unless it is one
of:
FALSE
NULL
""
An empty atomic vector
An atomic vector that contains only missing values
A logical vector that contains all FALSE
or missing values
An object of class "try-error"
A value that represents an unclicked actionButton()
Note in particular that the value 0
is considered truthy, even though
as.logical(0)
is FALSE
.
If the built-in rules for truthiness do not match your requirements, you can
always work around them. Since FALSE
is falsy, you can simply provide
the results of your own checks to req
:
req(input$a != 0)
Using req(FALSE)
You can use req(FALSE)
(i.e. no condition) if you've already performed
all the checks you needed to by that point and just want to stop the reactive
chain now. There is no advantange to this, except perhaps ease of readibility
if you have a complicated condition to check for (or perhaps if you'd like to
divide your condition into nested if
statements).
Using cancelOutput = TRUE
When req(..., cancelOutput = TRUE)
is used, the "silent" exception is
also raised, but it is treated slightly differently if one or more outputs are
currently being evaluated. In those cases, the reactive chain does not proceed
or update, but the output(s) are left is whatever state they happen to be in
(whatever was their last valid state).
Note that this is always going to be the case if
this is used inside an output context (e.g. output$txt <- ...
). It may
or may not be the case if it is used inside a non-output context (e.g.
reactive()
, observe()
or observeEvent()
)
--- depending on whether or not there is an output$...
that is triggered
as a result of those calls. See the examples below for concrete scenarios.
## Only run examples in interactive R sessions if (interactive()) { ui <- fluidPage( textInput('data', 'Enter a dataset from the "datasets" package', 'cars'), p('(E.g. "cars", "mtcars", "pressure", "faithful")'), hr(), tableOutput('tbl') ) server <- function(input, output) { output$tbl <- renderTable({ ## to require that the user types something, use: `req(input$data)` ## but better: require that input$data is valid and leave the last ## valid table up req(exists(input$data, "package:datasets", inherits = FALSE), cancelOutput = TRUE) head(get(input$data, "package:datasets", inherits = FALSE)) }) } shinyApp(ui, server) }