聆听清单中的反应式

时间:2020-10-16 15:21:39

标签: r shiny shiny-reactivity

我正在尝试将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数量取决于某些输入来发挥作用。

问题

我认为在我的代码中,renderPrint的{​​{1}}仅在启动时被调用。它意识到没有dbg1上下文(实际上仅在以后添加),因此永远不会回想它。在reactive的情况下,它看到至少一个反应,因此又回来了。因此,我想我必须使dbg1本身具有反应性(如@stefan指出的那样)

2 个答案:

答案 0 :(得分:2)

不确定最终要达到的目标。但是在this post之后,您可以像这样使用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)

enter image description here

答案 1 :(得分:0)

我猜是问题在于,dbg1首先检查l1时,它看不到任何反应性上下文(这是事实)。但是,它并没有意识到l1最终包含一些reactives,并且从不“调用”它。

因此,我认为我们必须使l1更具反应性(由@Stefan启发):

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())) 
}