收听列表​​中的反应

Listen to reactives in list

我正在尝试将 reactives 添加到列表中并听取他们的意见。我不明白为什么在下面的代码中我在 dbg1 中看不到任何输出,而它在 dgb2.

中工作

唯一的区别是 l2 将在启动时包含一个 reactive,而 l1 仅在第一次按下按钮后才包含,但其他方面相同。

有什么解释吗?

library(shiny)
library(purrr)

ui <- fluidPage(
   actionButton("add1", "Add to List 1"), 
   actionButton("add2", "Add to List 2"), 
   actionButton("rnd", "Generate Random"),
   verbatimTextOutput("dbg1"),
   verbatimTextOutput("dbg2"))

server <- function(input, output, session) {
   l1 <- l2 <- list()
   
   observeEvent(input$add1, {
      l1 <<- c(l1, reactive({
         input$rnd
         sample(100, 1)
      }))
   })
   
   observeEvent(input$add2, {
      l2 <<- c(l2, reactive({
         input$rnd
         sample(100, 1)
      }))
   }, ignoreNULL = FALSE)
   
   output$dbg1 <- renderPrint(map(l1, ~ .x()))
   output$dbg2 <- renderPrint(map(l2, ~ .x())) 
}

shinyApp(ui, server)

阅读@stefan 的回答和@starja 的评论后,我想更准确地呈现问题。

目标

我想要一个 reactives 的动态容器。也就是说,动态创建的数量 reactives,它们根据某些输入执行它们的操作。

问题

我认为在我的代码中 dbg1renderPrint 仅在启动时调用。它意识到没有 reactive 上下文(确实只是后来添加的)因此永远不会回忆起它。在 dbg1 的情况下,它至少看到一个反应并因此返回。所以我想我必须使 l1 本身具有反应性(正如@stefan 所指出的)

不确定您最终要达到什么目的。但是在 之后,您可以更新您的列表并通过使用 reactiveVal 来打印它们,如下所示:

library(shiny)
library(purrr)

ui <- fluidPage(
  actionButton("add1", "Add to List 1"), 
  actionButton("add2", "Add to List 2"), 
  actionButton("rnd", "Generate Random"),
  verbatimTextOutput("dbg1"),
  verbatimTextOutput("dbg2"))

server <- function(input, output, session) {
  l1 <- reactiveVal(value = list())
  l2 <- reactiveVal(value = list())
  
  rnd <- eventReactive(input$rnd, {
    sample(100, 1)
  })
  
  observeEvent(input$add1, {
    old_value <- l1()
    l1(c(old_value, rnd()))
  })
  observeEvent(input$add2, {
    old_value <- l2()
    l2(c(old_value, rnd()))
  })
  
  output$dbg1 <- renderPrint(l1())
  output$dbg2 <- renderPrint(l2()) 
}

shinyApp(ui, server)

我猜问题是当 dbg1 第一次检查 l1 时,它没有看到任何反应上下文(这是真的)。但是,它确实没有意识到 l1 最终包含一些 reactives 并且从不“召回”它。

因此,我认为我们必须通过使其本身具有反应性(受@Stefan 启发)来更明确地说明 l1

server <- function(input, output, session) {
   l1 <- l2 <- list()

   r1 <- reactiveVal(list())
   r2 <- reactiveVal(list())
   
   observeEvent(input$add1, {
      r1(c(r1(), reactive({
         input$rnd
         sample(100, 1)
      })))
   })
   
   observeEvent(input$add2, {
      r2(c(r2(), reactive({
         input$rnd
         sample(100, 1)
      })))
      
   }, ignoreNULL = FALSE)
   
   output$dbg1 <- renderPrint(map(r1(), ~ .x()))
   output$dbg2 <- renderPrint(map(r2(), ~ .x())) 
}