具有“全局”反应值的ShinyModules

问题描述

我有一个大型的闪亮应用程序,其中多个元素会更改reactiveVal。现在,我想移植该应用程序以使用闪亮的模块,以便能够对其进行更适当的测试。但是我无法访问服务器功能内定义的反应性值。

MWE

到目前为止,一个突出我思考过程的简单应用是这款计数器应用。 该应用程序包含两个模块:counterdisplay

  • counter单击按钮即可增加无功计数器值
  • display观察计数器并将其输出显示在文本字段中

应用程序的主要部分是一个名为counter_reactive的“中央”反应值,该值包含当前计数。 该值由counter设置,并由display模块元素读取。

library(shiny)

######################
# Counter Module
counter_UI <- function(id) {
  ns <- NS(id)
  tagList(
    actionButton(ns("button"),"Increase Count")
  )
}
counter <- function(input,output,session) {
  observeEvent(input$button,{
  counter_reactive(counter_reactive() + 1)
    cat("Increase Counter by 1 to",counter_reactive(),"\n")
  })
}

######################
# display Module
display_UI <- function(id) {
  ns <- NS(id)
  tagList(
    verbatimtextoutput(ns("text_output"))
  )
}
display <- function(input,session) {
  observe({
    cat("Print Value of Counter\n")
    output$text_output <- renderText(sprintf("Counter is Now %i",counter_reactive()))
  })
}

######################
# Rest of the Shiny App
ui <- fluidPage(
  counter_UI("counter1"),display_UI("display1")
)

server <- function(input,session) {
  # Note that counter_reactive is defined inside the "global" server function,# as multiple modules should read and write to it. 
  counter_reactive <- reactiveVal(0)
  
  callModule(counter,"counter1")
  callModule(display,"display1")
}

shinyApp(ui,server)

但是,此应用引发了错误Warning: Error in counter_reactive: Could not find function "counter_reactive"。 有什么想法如何获取/更改模块内部的无功值?

解决方法

将Rubber-Ducky-Debugging(也称为SO-Question编写调试)进行救援,此方法有效:

只需将反应值传递给像这样的函数

counter <- function(input,output,session,counter_reactive) {
  observeEvent(input$button,{
    counter_reactive(counter_reactive() + 1)
    cat("Increase Counter by 1 to",counter_reactive(),"\n")
  })
}

display <- function(input,counter_reactive) {
  observe({
    cat("Print Value of Counter\n")
    output$text_output <- renderText(sprintf("Counter is now %i",counter_reactive()))
  })
}

server <- function(input,session) {
  
  counter_reactive <- reactiveVal(0)
  
  callModule(counter,"counter1",counter_reactive)
  callModule(display,"display1",counter_reactive)
}