此问题与this one有关。这两者可以生成相同的功能,但实现略有不同。一个显着的区别是def myfunct (n: Int, steps: Int) = n match {
case 1 => steps
case even if n % 2 == 0 => // stuff
case odd => // other stuff
是一个可以有多个值的容器,例如reactiveValue
。在shiny documentation功能通常使用input$
实现,但在大多数情况下,我发现reactive()
更方便。这里有捕获吗?我可能没有注意到这两者之间是否存在其他重大差异?这两个代码片段是否相同?
查看使用以下内容实施的example code:
反应性表达:
reactiveValues()
反应值:
library(shiny)
ui <- fluidPage(
shiny::numericInput(inputId = 'n',label = 'n',value = 2),
shiny::textOutput('nthValue'),
shiny::textOutput('nthValueInv')
)
fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))
server<-shinyServer(function(input, output, session) {
currentFib <- reactive({ fib(as.numeric(input$n)) })
output$nthValue <- renderText({ currentFib() })
output$nthValueInv <- renderText({ 1 / currentFib() })
})
shinyApp(ui = ui, server = server)
答案 0 :(得分:56)
有一个问题,虽然它在你的例子中不会发挥作用。
闪亮开发人员设计reactive()
为 lazy ,这意味着其中包含的表达式只会在其中一个受属者调用时执行。当其中一个反应依赖项发生更改时,它会清除其缓存并通知其自己的依赖项,但在由其中一个依赖项要求之前,它本身不会执行。 (因此,如果,例如,它唯一的依赖项是隐藏选项卡上的textOutput()
元素,除非并且直到该选项卡打开,否则它将无法实际执行。)
observe()
渴望;它包含的表达式将立即执行,只要其中一个反应依赖项发生更改 - 即使它的任何依赖项不需要它的值(事实上即使具有)没有家属)。当您因为副作用而调用observe()
时,这种渴望是可取的,但当您仅使用它时,它可能浪费将其内容的返回值传递给其他反应式表达式或端点。
observe()
/ reactiveValue ()
组合的行为。
答案 1 :(得分:35)
这两个结构确实相似,而且很多时候你可以用任何一个来解决你的问题。但使用其中一种通常更有意义。
在斐波纳契案例中,我认为使用reactive()
表达式更有意义,因为currentFib
是一个应该在非常具体的可预测时间内修改的值(即input$n
更改时,应该相应地更新反应值,或者对此变化作出反应。
但在其他一些情况下,使用reactiveValues
可能更简单,更好。我将展示两个例子。
首先,每当你有一个你认为具有某种状态的变量时(而不仅仅是对正在更新的不同值做出反应),我认为使用reactiveValues
更好
示例:
library(shiny)
ui <- fluidPage(
"Total:",
textOutput("total", inline = TRUE),
actionButton("add1", "Add 1"),
actionButton("add5", "Add 5")
)
server <- function(input, output, session) {
values <- reactiveValues(total = 0)
observeEvent(input$add1, {
values$total <- values$total + 1
})
observeEvent(input$add5, {
values$total <- values$total + 5
})
output$total <- renderText({
values$total
})
}
shinyApp(ui = ui, server = server)
在上面的代码中,我们有一个total
变量,它具有可变状态,并且将其视为典型变量并使用它就更直观。这是我使用reactiveValues
时最常见的情况。
当变量可以在多个位置更新时,我也使用reactiveValues
。要从fibonacci示例中借用,请考虑以下闪亮应用,其中n
数字可以由两个输入中的任何一个设置:
library(shiny)
fib <- function(n) ifelse(n < 3, 1, fib(n - 1) + fib(n - 2))
ui <- fluidPage(
selectInput("nselect", "Choose a pre-defined number", 1:10),
numericInput("nfree", "Or type any number", 1),
"Fib number:",
textOutput("nthval", inline = TRUE)
)
server <- function(input, output, session) {
values <- reactiveValues(n = 1)
observeEvent(input$nselect, {
values$n <- input$nselect
})
observeEvent(input$nfree, {
values$n <- input$nfree
})
output$nthval <- renderText({
fib(as.integer(values$n))
})
}
shinyApp(ui = ui, server = server)
这个例子在fibonacci的上下文中看起来有点奇怪,但希望你能看到在其他一些复杂的应用程序中,有时你可能希望在不同的地方设置一个变量的值,它可以更直观地做它使用reactiveValue而不是必须在一个块中实现的反应式表达式。
希望这有用并且有意义。当然这只是我对这个主题的个人看法,它不一定是闪亮的开发者想要的,但这就是我学会使用这两种方法的方法。