mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-13 08:57:57 -05:00
Compare commits
1 Commits
switchInpu
...
getCurrent
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89026ee1ae |
@@ -84,6 +84,7 @@ export(fluidPage)
|
|||||||
export(fluidRow)
|
export(fluidRow)
|
||||||
export(formatStackTrace)
|
export(formatStackTrace)
|
||||||
export(freezeReactiveValue)
|
export(freezeReactiveValue)
|
||||||
|
export(getCurrentObserver)
|
||||||
export(getDefaultReactiveDomain)
|
export(getDefaultReactiveDomain)
|
||||||
export(getShinyOption)
|
export(getShinyOption)
|
||||||
export(h1)
|
export(h1)
|
||||||
|
|||||||
125
R/reactives.R
125
R/reactives.R
@@ -703,6 +703,10 @@ execCount <- function(x) {
|
|||||||
|
|
||||||
# Observer ------------------------------------------------------------------
|
# Observer ------------------------------------------------------------------
|
||||||
|
|
||||||
|
# The initial value of "current observer" is NULL (and will always be NULL,
|
||||||
|
# except when within the scope of the observe or observeEvent)
|
||||||
|
.globals$currentObserver <- NULL
|
||||||
|
|
||||||
Observer <- R6Class(
|
Observer <- R6Class(
|
||||||
'Observer',
|
'Observer',
|
||||||
portable = FALSE,
|
portable = FALSE,
|
||||||
@@ -814,6 +818,8 @@ registerDebugHook("observerFunc", environment(), label)
|
|||||||
run = function() {
|
run = function() {
|
||||||
ctx <- .createContext()
|
ctx <- .createContext()
|
||||||
.execCount <<- .execCount + 1L
|
.execCount <<- .execCount + 1L
|
||||||
|
.globals$currentObserver <- self
|
||||||
|
on.exit(.globals$currentObserver <- NULL) # On exit, set it back to NULL
|
||||||
ctx$run(.func)
|
ctx$run(.func)
|
||||||
},
|
},
|
||||||
onInvalidate = function(callback) {
|
onInvalidate = function(callback) {
|
||||||
@@ -904,6 +910,125 @@ registerDebugHook("observerFunc", environment(), label)
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#' Return the current observer
|
||||||
|
#'
|
||||||
|
#' This function is useful when you want to access an observer's methods or
|
||||||
|
#' variables directly. For example, you may have logic that destroys or
|
||||||
|
#' suspends the observer (from within its own scope) on some condition.
|
||||||
|
#'
|
||||||
|
#' This function works by returning the observer that is currently being run
|
||||||
|
#' when \code{getCurrentObserver()} is called. If there is no observer being
|
||||||
|
#' run (for example, if you called it from outside of a reactive context),
|
||||||
|
#' it will always return \code{NULL}. There are a few subtleties, however.
|
||||||
|
#' Consider the following five situations:
|
||||||
|
#'
|
||||||
|
#' \enumerate{
|
||||||
|
#' \item \code{getCurrentObserver() #outside of a reactive context}
|
||||||
|
#' \item \code{observe({ getCurrentObserver() }) }
|
||||||
|
#' \item \code{observe({ (function(){ getCurrentObserver() })() )} }
|
||||||
|
#' \item \code{observe({ isolate({ getCurrentObserver() }) }) }
|
||||||
|
#' \item \code{observe({ reactive({ getCurrentObserver() }) }) }
|
||||||
|
#' }
|
||||||
|
#'
|
||||||
|
#' In (1), since you're outside of a reactive context, we've already
|
||||||
|
#' established that \code{getCurrentObserver()} will return \code{NULL}.
|
||||||
|
#' In (2), we have the "vanilla" case, in which \code{getCurrentObserver()}
|
||||||
|
#' is called directly from within the body of the \code{observe} call.
|
||||||
|
#' This returns that observer. So far, so good. The problem comes with
|
||||||
|
#' the last three cases -- should we be able to "retrieve" the outer
|
||||||
|
#' observer if we're inside an inner function's scope, or inside of an
|
||||||
|
#' \code{isolate} or a \code{reactive} block?
|
||||||
|
#'
|
||||||
|
#' Before we can even asnwer that, there is an important distinction to
|
||||||
|
#' be made here: are function calls, \code{reactive} calls and
|
||||||
|
#' \code{isolate} blocks the same \emph{type} of thing? As far as Shiny
|
||||||
|
#' is concerned, the answer is no. Shiny-specific things (like observers,
|
||||||
|
#' reactives and code inside of an \code{isolate} chunk) exist in what we
|
||||||
|
#' call reactive contexts. Each run of an observer or a reactive is
|
||||||
|
#' associated with a particular reactive context. But regular functions
|
||||||
|
#' have no relation to reactive contexts. So, while calling a regular
|
||||||
|
#' function inside of an observer does not change the reactive context,
|
||||||
|
#' calling a \code{reactive} or \code{isolate} certainly does.
|
||||||
|
#'
|
||||||
|
#' With this distinction in mind, we can refine our definition of
|
||||||
|
#' \code{getCurrentObserver()} as follows: it returns the observer (if any)
|
||||||
|
#' that is currently running, as long as it is called from within the
|
||||||
|
#' same reactive context that was created when the observer started
|
||||||
|
#' running. If the reactive context changed (most likely because of a
|
||||||
|
#' call to \code{reactive} or \code{isolate}), \code{getCurrentObserver}
|
||||||
|
#' will return \code{NULL}. (There is another common way that the reactive
|
||||||
|
#' context can change inside an observer, which is if there is a second,
|
||||||
|
#' nested observer. In this case, \code{getCurrentObserver()} will return
|
||||||
|
#' the second, nested observer, since that is the one that is actually
|
||||||
|
#' running at that time.)
|
||||||
|
#'
|
||||||
|
#' So to recap, here's the return value for each of the five situations:
|
||||||
|
#' \enumerate{
|
||||||
|
#' \item \code{NULL}
|
||||||
|
#' \item the observer
|
||||||
|
#' \item the observer
|
||||||
|
#' \item \code{NULL}
|
||||||
|
#' \item \code{NULL}
|
||||||
|
#' }
|
||||||
|
#'
|
||||||
|
#' Now, you may be wondering why \code{getCurrentObserver()} should't be able
|
||||||
|
#' to get the running observer even if the reactive context changes. This isn't
|
||||||
|
#' technically impossible. In fact, if you want this behavior for some reason,
|
||||||
|
#' you can set the argument \code{dig} to be \code{TRUE}, so that the function
|
||||||
|
#' will "dig" through the reactive contexts until it retrieves the one for the
|
||||||
|
#' observer and returns the observer.
|
||||||
|
#'
|
||||||
|
#' So, with \code{dig = TRUE}, here's the return value for each of the five
|
||||||
|
#' situations:
|
||||||
|
#' \enumerate{
|
||||||
|
#' \item \code{NULL}
|
||||||
|
#' \item the observer
|
||||||
|
#' \item the observer
|
||||||
|
#' \item the observer
|
||||||
|
#' \item the observer
|
||||||
|
#' }
|
||||||
|
#'
|
||||||
|
#' The reason that this is not the default (or even encouraged) is because
|
||||||
|
#' things can get messy quickly when you cross reactive contexts at will.
|
||||||
|
#' For example, the return value of a \code{reactive} call is cached and that
|
||||||
|
#' reactive is not re-run unless its reactive dependencies change. If that
|
||||||
|
#' reactive has a call to \code{getCurrentObserver()}, this can produce
|
||||||
|
#' undesirable and unintuitive results.
|
||||||
|
#'
|
||||||
|
#' @param dig If \code{FALSE} (default), \code{getCurrentObserver} will only
|
||||||
|
#' return the observer if it's invoked directly from within the observer's
|
||||||
|
#' body or from a regular function. If \code{TRUE}, it will always return
|
||||||
|
#' the observer (if it exists on the stack), even if it's invoked from
|
||||||
|
#' within a \code{reactive} or an \code{isolate} scope. See below for more
|
||||||
|
#' information.
|
||||||
|
#'
|
||||||
|
#' @return The observer (created with a call to either \code{observe} or to
|
||||||
|
#' \code{observeEvent}) that is currently running.
|
||||||
|
#'
|
||||||
|
#' @seealso \code{\link{observe}}
|
||||||
|
#'
|
||||||
|
#' @examples
|
||||||
|
#' ## Only run examples in interactive R sessions
|
||||||
|
#' if (interactive()) {
|
||||||
|
#' shinyApp(
|
||||||
|
#' ui = basicPage( actionButton("go", "Go")),
|
||||||
|
#' server = function(input, output, session) {
|
||||||
|
#' observeEvent(input$go, {
|
||||||
|
#' print(paste("This will only be printed once; all",
|
||||||
|
#' "subsequent button clicks won't do anything"))
|
||||||
|
#' getCurrentObserver()$destroy()
|
||||||
|
#' })
|
||||||
|
#' }
|
||||||
|
#' )
|
||||||
|
#' }
|
||||||
|
#' @export
|
||||||
|
getCurrentObserver <- function(dig = FALSE) {
|
||||||
|
o <- .globals$currentObserver
|
||||||
|
ctx <- getCurrentContext()
|
||||||
|
if (!dig && !is.null(o) && ctx$id != o$.ctx$id) o <- NULL
|
||||||
|
o
|
||||||
|
}
|
||||||
|
|
||||||
#' Create a reactive observer
|
#' Create a reactive observer
|
||||||
#'
|
#'
|
||||||
#' Creates an observer from the given expression.
|
#' Creates an observer from the given expression.
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ sd_section("Reactive constructs",
|
|||||||
"makeReactiveBinding",
|
"makeReactiveBinding",
|
||||||
"observe",
|
"observe",
|
||||||
"observeEvent",
|
"observeEvent",
|
||||||
|
"getCurrentObserver",
|
||||||
"reactive",
|
"reactive",
|
||||||
"reactiveFileReader",
|
"reactiveFileReader",
|
||||||
"reactivePoll",
|
"reactivePoll",
|
||||||
|
|||||||
124
man/getCurrentObserver.Rd
Normal file
124
man/getCurrentObserver.Rd
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
% Generated by roxygen2: do not edit by hand
|
||||||
|
% Please edit documentation in R/reactives.R
|
||||||
|
\name{getCurrentObserver}
|
||||||
|
\alias{getCurrentObserver}
|
||||||
|
\title{Return the current observer}
|
||||||
|
\usage{
|
||||||
|
getCurrentObserver(dig = FALSE)
|
||||||
|
}
|
||||||
|
\arguments{
|
||||||
|
\item{dig}{If \code{FALSE} (default), \code{getCurrentObserver} will only
|
||||||
|
return the observer if it's invoked directly from within the observer's
|
||||||
|
body or from a regular function. If \code{TRUE}, it will always return
|
||||||
|
the observer (if it exists on the stack), even if it's invoked from
|
||||||
|
within a \code{reactive} or an \code{isolate} scope. See below for more
|
||||||
|
information.}
|
||||||
|
}
|
||||||
|
\value{
|
||||||
|
The observer (created with a call to either \code{observe} or to
|
||||||
|
\code{observeEvent}) that is currently running.
|
||||||
|
}
|
||||||
|
\description{
|
||||||
|
This function is useful when you want to access an observer's methods or
|
||||||
|
variables directly. For example, you may have logic that destroys or
|
||||||
|
suspends the observer (from within its own scope) on some condition.
|
||||||
|
}
|
||||||
|
\details{
|
||||||
|
This function works by returning the observer that is currently being run
|
||||||
|
when \code{getCurrentObserver()} is called. If there is no observer being
|
||||||
|
run (for example, if you called it from outside of a reactive context),
|
||||||
|
it will always return \code{NULL}. There are a few subtleties, however.
|
||||||
|
Consider the following five situations:
|
||||||
|
|
||||||
|
\enumerate{
|
||||||
|
\item \code{getCurrentObserver() #outside of a reactive context}
|
||||||
|
\item \code{observe({ getCurrentObserver() }) }
|
||||||
|
\item \code{observe({ (function(){ getCurrentObserver() })() )} }
|
||||||
|
\item \code{observe({ isolate({ getCurrentObserver() }) }) }
|
||||||
|
\item \code{observe({ reactive({ getCurrentObserver() }) }) }
|
||||||
|
}
|
||||||
|
|
||||||
|
In (1), since you're outside of a reactive context, we've already
|
||||||
|
established that \code{getCurrentObserver()} will return \code{NULL}.
|
||||||
|
In (2), we have the "vanilla" case, in which \code{getCurrentObserver()}
|
||||||
|
is called directly from within the body of the \code{observe} call.
|
||||||
|
This returns that observer. So far, so good. The problem comes with
|
||||||
|
the last three cases -- should we be able to "retrieve" the outer
|
||||||
|
observer if we're inside an inner function's scope, or inside of an
|
||||||
|
\code{isolate} or a \code{reactive} block?
|
||||||
|
|
||||||
|
Before we can even asnwer that, there is an important distinction to
|
||||||
|
be made here: are function calls, \code{reactive} calls and
|
||||||
|
\code{isolate} blocks the same \emph{type} of thing? As far as Shiny
|
||||||
|
is concerned, the answer is no. Shiny-specific things (like observers,
|
||||||
|
reactives and code inside of an \code{isolate} chunk) exist in what we
|
||||||
|
call reactive contexts. Each run of an observer or a reactive is
|
||||||
|
associated with a particular reactive context. But regular functions
|
||||||
|
have no relation to reactive contexts. So, while calling a regular
|
||||||
|
function inside of an observer does not change the reactive context,
|
||||||
|
calling a \code{reactive} or \code{isolate} certainly does.
|
||||||
|
|
||||||
|
With this distinction in mind, we can refine our definition of
|
||||||
|
\code{getCurrentObserver()} as follows: it returns the observer (if any)
|
||||||
|
that is currently running, as long as it is called from within the
|
||||||
|
same reactive context that was created when the observer started
|
||||||
|
running. If the reactive context changed (most likely because of a
|
||||||
|
call to \code{reactive} or \code{isolate}), \code{getCurrentObserver}
|
||||||
|
will return \code{NULL}. (There is another common way that the reactive
|
||||||
|
context can change inside an observer, which is if there is a second,
|
||||||
|
nested observer. In this case, \code{getCurrentObserver()} will return
|
||||||
|
the second, nested observer, since that is the one that is actually
|
||||||
|
running at that time.)
|
||||||
|
|
||||||
|
So to recap, here's the return value for each of the five situations:
|
||||||
|
\enumerate{
|
||||||
|
\item \code{NULL}
|
||||||
|
\item the observer
|
||||||
|
\item the observer
|
||||||
|
\item \code{NULL}
|
||||||
|
\item \code{NULL}
|
||||||
|
}
|
||||||
|
|
||||||
|
Now, you may be wondering why \code{getCurrentObserver()} should't be able
|
||||||
|
to get the running observer even if the reactive context changes. This isn't
|
||||||
|
technically impossible. In fact, if you want this behavior for some reason,
|
||||||
|
you can set the argument \code{dig} to be \code{TRUE}, so that the function
|
||||||
|
will "dig" through the reactive contexts until it retrieves the one for the
|
||||||
|
observer and returns the observer.
|
||||||
|
|
||||||
|
So, with \code{dig = TRUE}, here's the return value for each of the five
|
||||||
|
situations:
|
||||||
|
\enumerate{
|
||||||
|
\item \code{NULL}
|
||||||
|
\item the observer
|
||||||
|
\item the observer
|
||||||
|
\item the observer
|
||||||
|
\item the observer
|
||||||
|
}
|
||||||
|
|
||||||
|
The reason that this is not the default (or even encouraged) is because
|
||||||
|
things can get messy quickly when you cross reactive contexts at will.
|
||||||
|
For example, the return value of a \code{reactive} call is cached and that
|
||||||
|
reactive is not re-run unless its reactive dependencies change. If that
|
||||||
|
reactive has a call to \code{getCurrentObserver()}, this can produce
|
||||||
|
undesirable and unintuitive results.
|
||||||
|
}
|
||||||
|
\examples{
|
||||||
|
## Only run examples in interactive R sessions
|
||||||
|
if (interactive()) {
|
||||||
|
shinyApp(
|
||||||
|
ui = basicPage( actionButton("go", "Go")),
|
||||||
|
server = function(input, output, session) {
|
||||||
|
observeEvent(input$go, {
|
||||||
|
print(paste("This will only be printed once; all",
|
||||||
|
"subsequent button clicks won't do anything"))
|
||||||
|
getCurrentObserver()$destroy()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\seealso{
|
||||||
|
\code{\link{observe}}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user