我已经阅读了所有关于react 式编程的书籍.我有点困惑.以下所有方法都有效,但首选的方法是什么?为什么?显然,下面的例子很简单,但是当我用任何一种方法创建一个更大的应用程序时,我会遇到麻烦吗?

我一直倾向于服务器代码#1中的风格.原因是,我能够分解if语句.对我来说,这似乎更具可读性.同样,下面的简单示例并不十分复杂,但您可以很容易地想象,服务器代码2和服务器代码3如何与大量嵌套的if/if-else语句混淆.

UI Code

library(shiny)

ui <- fluidPage(
  selectInput(inputId = 'choice',
              label = 'Choice',
              choice = c('Hello','Goodbye'),
              selected = c('Hello')
  ),

  textOutput('result')

)

Server Code 1

server <- function(input,output,session)({

  text <- reactiveValues()

  observe({
    if (input$choice == 'Hello') {
      text$result <- 'Hi there'
      }
    })

  observe({
    if (input$choice == 'Goodbye') {
      text$result <- 'See you later'
      }
    })

  output$result <- renderText({
    text$result
  })

})

shinyApp(ui = ui, server = server)

Server Code 2

server <- function(input,output,session)({

  getStatus <- reactive({

    if (input$choice == 'Hello') {
      'Hi there'
    } else if (input$choice == 'Goodbye'){
      'See you later'
    }
  })

  output$result <- renderText({
    getStatus()
  })

})

shinyApp(ui = ui, server = server)

Server Code 3

server <- function(input,output,session)({

  text <- reactiveValues()

  observeEvent(input$choice,{
    if (input$choice == 'Hello') {
      text$result <- 'Hi there'
    } else if (input$choice == 'Goodbye') {
      text$result <- 'See you later'
    }
  })

  output$result <- renderText({
    text$result
  })

})

shinyApp(ui = ui, server = server)

推荐答案

首先,这些东西有点模棱两可,在某些方面不是很直观,甚至在shiny 的博客上也这么说!

以下是我对这个话题的最好理解..

Lets start with 100

被动功能允许用户监控输入或其他变化变量的状态,并返回代码中其他地方使用的值.对react 变量的监控被认为是懒惰的,"Reactive expressions use lazy evaluation; that is, when their dependencies change, they don't re-execute right away but rather wait until they are called by someone else.(100".在示例2中,您很好地展示了这一点,因为您可以在renderText环境中调用该变量,一旦调用了react 调用中的代码,就会执行并重新计算该变量.

对于科学迷来说,这很像量子力学,通过调用react 变量(观察它)导致它通过重新判断而改变,太长时间?

Now to 100

Observe与reactive类似,主要区别在于它不会将任何值返回到除自身环境之外的任何其他环境,并且它不是懒惰的.当这些值发生变化时,观察函数continually monitors any changes in all reactive values within its environment并在其环境中运行代码.因此,observe不是一个"懒惰"的判断,因为它不会等到被调用后再重新判断.再次注意,您不能从observe分配变量.

为了便于实验:

server <- function(input,output,session)({

   observe({
   if (input$choice == 'Hello') {
      getStatus <- 'Hi there'
    }
  })

  observe({
    if (input$choice == 'Goodbye') {
      getStatus <- 'See you later'
    }
  })

  output$result <- renderText({
    getStatus
  })

})

shinyApp(ui = ui, server = server)

enter image description here

需要注意的是,在observe中执行代码期间,我们可以操纵外部环境的react 变量.在你的例子中,你分配text <- reactiveValues(),然后通过调用text$result <- 'Hi there'来操作它.我们也可以做一些事情,比如更新selectInput选项,或者其他shiny 的小部件,但是我们不能在这个环境中分配任何非react 性变量,比如上面例子中的getStatus.observe份文件中提到了这个 idea ,

"观察者就像一个react 式表达式,因为它可以读取react 式值并调用react 式表达式,当这些依赖项发生变化时,它会自动重新执行.但与react 式表达式不同,它不会产生结果,也不能用作其他react 式表达式的输入.因此,观察者只对其副作用有用s(例如,执行I/O)(Source)"

Lastly, 100

使用observeEvent的最佳方式是将其视为已定义的触发器,因为它监视一个事件或变量中的更改,然后在事件发生时触发.我最常用它来观察按钮的输入,因为这是一个定义的事件,我希望在按下按钮后发生事情.它使用isolate环境,我认为这是这个函数工作原理的完美名称.

在这个环境中,我们可以调用一组react 变量,但我们只定义一个作为触发器.observeEventobserve之间的主要区别在于触发器,因为observe在任何变化时都会运行,observeEvent等待触发器.请注意,此环境与observe类似,因为它不返回非react 性变量.

Summary

下面是一个将所有这些 idea 结合在一起的例子:

library(shiny)

ui<-
 fluidPage(
   fluidRow(
     column(4,
      h2("Reactive Test"),
      textInput("Test_R","Test_R"),
      textInput("Test_R2","Test_R2"),
      textInput("Test_R3","Test_R3"),
      tableOutput("React_Out")
    ),
     column(4,
      h2("Observe Test"),
      textInput("Test","Test"),
      textInput("Test2","Test2"),
      textInput("Test3","Test3"),
      tableOutput("Observe_Out")
    ),
    column(4,
      h2("Observe Event Test"),
      textInput("Test_OE","Test_OE"),
      textInput("Test_OE2","Test_OE2"),
      textInput("Test_OE3","Test_OE3"),
      tableOutput("Observe_Out_E"),
      actionButton("Go","Test")
    )

    ),
  fluidRow(
    column(8,
    h4("Note that observe and reactive work very much the same on the surface,
       it is when we get into the server where we see the differences, and how those
       can be exploited for diffrent uses.")
  ))

  )

server<-function(input,output,session){

# Create a reactive Evironment. Note that we can call the varaible outside same place
# where it was created by calling Reactive_Var(). When the varaible is called by
# renderTable is when it is evaluated. No real diffrence on the surface, all in the server.

Reactive_Var<-reactive({c(input$Test_R, input$Test_R2, input$Test_R3)})

output$React_Out<-renderTable({
  Reactive_Var()
  })

# Create an observe Evironment. Note that we cannot access the created "df" outside 
# of the env. A, B,and C will update with any input into any of the three Text Feilds.
observe({
  A<-input$Test
  B<-input$Test2
  C<-input$Test3
  df<-c(A,B,C)
  output$Observe_Out<-renderTable({df})
  })

#We can change any input as much as we want, but the code wont run until the trigger
# input$Go is pressed.
observeEvent(input$Go, {
  A<-input$Test_OE
  B<-input$Test_OE2
  C<-input$Test_OE3
  df<-c(A,B,C)
  output$Observe_Out_E<-renderTable({df})
})

}
shinyApp(ui, server)

reactive

observe

observeEvent(多米诺效应)

eventReactive Create a variable,定义的触发器与observeEvent类似.当您需要一个因触发器而计算的被动变量时,而不是在调用它时,可以使用此选项.

我希望这会有所帮助,如果我的理解有误,或者可能会有更多的澄清,请随意编辑这个答案.

R相关问答推荐

基于现有类创建类的打印方法(即,打印tibles更长时间)

为什么st_join(ob1,ob2,left = True)返回具有比ob1更多功能的sf对象?

如何按排序顺序打印一个框架中所有精确的唯一值?

使用gcuminc,如何使用逗号格式化风险表?

基于多列将值链接到NA

如何通过Docker部署我的shiny 应用程序(多个文件)

当我们有多个特殊字符时,使用gsub删除名称和代码'

如何使用tryCatch执行语句并忽略警告?

根据列A中的差异变异列,其中行由列B中的相对值标识

Select 季度月值

如何在ggplot2中绘制具有特定 colored颜色 的连续色轮

如何使这些react 表对象相互独立?

如何在PrePlot()中将多个元素设置为斜体

使用来自嵌套列和非嵌套列的输入的PURRR:MAP和dplyr::Mariate

有毒元素与表观遗传年龄的回归模型

合并多个数据帧,同时将它们的名称保留为列名?

使用卡环从R中的列中删除单位(&C)

如果缺少时间,如何向日期-时间列添加时间

线性混合模型方差分析的非参数方法及幂计算

将一个二次函数叠加到一个被封装为facet的ggplot2对象的顶部