Handling missing inputs with req(...)
By: Joe Cheng
When writing Shiny apps, it’s fairly common to have a reactive expression or output that can only proceed under certain conditions.
Perhaps we need to wait until the user chooses a value from a
selectInput or clicks an
actionButton, and if such conditions are not met, the output should not be shown.
Or if your app uses
renderUI to dynamically populate the app’s input controls, then for a few moments during app startup, the inputs you depend on might not even exist.
If you write your application without considering such conditions, you may find your outputs rendering with ugly and confusing error messages. Here’s an example:
The value of
input$datasetName starts out as
"", which causes the
dataset reactive expression to fail.
A primitive solution is to add precondition checks to all reactive expressions and outputs, and return
NULL if any conditions are not met. Most (though not all) outputs will clear themselves if they are asked to render
See below as we add
if (...) return(NULL) to
While this does work, it seems a shame that such a simple app needs three different manual checks and early returns. If any new reactive expressions or outputs are introduced that depend on
dataset, they’ll also need to remember to check for null and return early.
Fortunately, there’s a better way.
req(...) function was introduced in Shiny 0.13 to simplify dealing with missing inputs and other preconditions.
req is short for “require”, so
req(x) can be read as either “require
x to be available”.
req with one or more arguments.
req will evaluate each argument one at a time, and if it encounters an argument that it considers to be “missing” or “false” (see below for exactly what this means), it will stop.
Here’s our previous example again, using
req this time:
As you can see,
dataset uses the
req function, and the outputs don’t do any checking. Unlike using
return(NULL), when you use
req to check your preconditions, a failure not only stops the current calculation (the
dataset reactive expression, in this case) but also any callers on the call stack. In this case, if the user has not chosen a dataset, then
output$table both stop upon calling
This is because when
req detects a failure, it doesn’t simply return, but actually raises an error by calling
You can think of
req as being like
base::stopifnot, with a couple of key differences:
First, the error raised by
reqis a special, “silent” error that Shiny knows shouldn’t actually be displayed to the user, nor printed to the console.
stopifnotsimply checks if its arguments are
reqhas a more complicated set of rules that determine what arguments trigger an error.
Truthy and falsy values
The terms “truthy” and “falsy” generally indicate whether a value, when coerced to a logical, is
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:
- 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
- A value that represents an unclicked
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, e.g.:
req(input$a != 0).
See also: validate/need
req causes outputs to stop silently, it’s not useful in situations where the user needs to be told what values are missing or what user actions need to be taken to proceed.
In that case, you need the more flexible validation feature, which provides a superset of
req’s features via the validate/need functions;
req(x) is mostly just shorthand for
validate(need(x, message = FALSE)).
The downside of
validate is that its API is more complicated and less intuitive than
req, so we recommend that you stick to
req whenever you can.
If you have questions about this article or would like to discuss ideas presented here, please post on RStudio Community. Our developers monitor these forums and answer questions periodically. See help for more help with all things Shiny.