rshinyrstudiornw

Detecting whether shiny runs the R code


I would like to run R code in two locations, in an Rnw file and as an interactive shiny R markdown document.

Thus, what I need, since interactive shiny components do not work in Rnw files, is a code snippet in R that detects whether to load the interactive code or not.

This seems to work, but it feels like a quick hack:

if (exists("input")) { # input is provided by shiny
    # interactive components like renderPlot for shiny
} else {
    # non-interactive code for Rnw file
}

Is there a stable solution or something like a global variable that I can access that says whether shiny is running at the moment? Or should I check whether the shiny package is loaded?

What's safest?


Solution

  • This information is provided directly via Shiny’s isRunning function.


    Outdated answer below:

    You can do the following:

    shiny_running = function () {
        # Look for `runApp` call somewhere in the call stack.
        frames = sys.frames()
        calls = lapply(sys.calls(), `[[`, 1)
        call_name = function (call)
            if (is.function(call)) '<closure>' else deparse(call)
        call_names = vapply(calls, call_name, character(1))
    
        target_call = grep('^runApp$', call_names)
    
        if (length(target_call) == 0)
            return(FALSE)
        
        # Found a function called `runApp`, verify that it’s Shiny’s.
        target_frame = frames[[target_call]]
        namespace_frame = parent.env(target_frame)
        isNamespace(namespace_frame) && environmentName(namespace_frame) == 'shiny'
    }
    

    Now you can simply use shiny_running() in code and get a logical value back that indicates whether the document is run as a Shiny app.

    This is probably (close to) the best way, according to a discussion on Shiny the mailing list — but do note the caveats mentioned in the discussion.

    Adapted from code in the “modules” package.

    Alternatively, the following works. It may be better suited for the Shiny/RMarkdown use-case, but requires the existence of the YAML front matter: It works by reading the runtime value from that.

    shiny_running = function ()
        identical(rmarkdown::metadata$runtime, 'shiny')