如何使用 reactiveValues 而不是 reactiveVal 作为模块参数?

How to use reactiveValues instead of reactiveVal as a module parameter?

提问人:pietrodito 提问时间:11/15/2023 最后编辑:pietrodito 更新时间:11/16/2023 访问量:32

问:

工作最小示例

我正在尝试禁用带有包的模块 UI。在主应用程序中,我使用一个名为 :shinyjsenabled


library(shiny)
library(shinyjs)

# ____________________________________________
##########
# MODULE #
##########

subUI <- function(id) {
  ns <- NS(id)
  tagList(
    useShinyjs(),
    actionButton(ns("click"), "CLICK!")
  )
}

subServer <- function(id, enabled) {
  stopifnot(is.reactive(enabled))
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        if(enabled()) {
          enable("click")
        } else {
          disable("click")
        }
      })
    }
  )
}

# ____________________________________________
##############
# MAIN APP   #
##############
ui <- fluidPage(
  actionButton("toggle", "Toggle"),
  subUI("sub")
)

server <- function(input, output, session) {
  
  enabled <- reactiveVal(TRUE)
  
  
  subServer("sub", enabled)
  
  observeEvent(input$toggle, { enabled(! enabled()) })
}

shinyApp(ui, server, options = list(
  launch.browser = TRUE
))

问题

在我的实际应用程序中,我有很多反应值需要处理,我正在使用而不是,但我没有设法适应上面的例子。我试过:reactiveValues()reactiveVal()


library(shiny)
library(shinyjs)

# ____________________________________________
##############
# SUB MODULE #
##############

subUI <- function(id) {
  ns <- NS(id)
  tagList(
    useShinyjs(),
    actionButton(ns("click"), "CLICK!")
  )
}

subServer <- function(id, enabled) {
  # stopifnot(is.reactive(enabled))
  
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        if(enabled) {
          enable("click")
        } else {
          disable("click")
        }
      })
    }
  )
}

# ____________________________________________
##############
# MAIN APP   #
##############
ui <- fluidPage(
  actionButton("toggle", "Toggle"),
  subUI("sub")
)

server <- function(input, output, session) {
  
  r <- reactiveValues()
  r$enabled <- TRUE
  
  subServer("sub", r$enabled)
  
  observeEvent(input$toggle, { r$enabled <- ! r$enabled })
}

shinyApp(ui, server, options = list(
  launch.browser = TRUE
))

注意:我不得不在子模块服务器中注释掉这一行,这引发了我无法理解的错误:# stopifnot(is.reactive(enabled))


Error in r$enabled : 
  Can't access reactive value 'enabled' outside of reactive consumer.

我认为这是处理反应性价值的目的......is.reactive()

R 闪亮 反应式 ShinyJS

评论

0赞 Limey 11/15/2023
关于你无法理解的错误......如消息所述,您只能访问响应式使用者内部的响应式。反应式消费者类似于 ,或 。所以,类似的东西应该有效。但可能有更好的方法可以做到这一点。observeobserveEventreactiveobserve({ stopifnot(is.reactive(enabled)) })
0赞 Limey 11/15/2023
您的(子)模块中定义在哪里?x()
0赞 pietrodito 11/15/2023
@Limey输入错误,但我不能同意你的第一条评论,因为你可以看到它在第一段代码中完美地工作。x()

答:

1赞 Nir Graham 11/15/2023 #1

下面是两个示例方法。 第一个,只是将 reactiveValue 包装在 reactive() 中,以便它与原始工作设计紧密结合。 第二个,通过整个 reactiveValues 对象并进行相关测试,并在原地使用它,也许是您正在搜索的内容,不清楚您更喜欢哪个。

1)

library(shiny)
library(shinyjs)

# ____________________________________________
##############
# SUB MODULE #
##############

subUI <- function(id) {
  ns <- NS(id)
  tagList(
    useShinyjs(),
    actionButton(ns("click"), "CLICK!")
  )
}

subServer <- function(id, enabled) {
  stopifnot(is.reactive(enabled))
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        if(enabled()) {
          enable("click")
        } else {
          disable("click")
        }
      })
    }
  )
}

# ____________________________________________
##############
# MAIN APP   #
##############
ui <- fluidPage(
  actionButton("toggle", "Toggle"),
  subUI("sub")
)

server <- function(input, output, session) {
  
  r <- reactiveValues()
  r$enabled <- TRUE
  
  
  subServer("sub", reactive(r$enabled))
  
  observeEvent(input$toggle, {
    r$enabled <- !r$enabled
    })
}

shinyApp(ui, server, options = list(
  launch.browser = TRUE
))

2)

library(shiny)
library(shinyjs)

# ____________________________________________
##############
# SUB MODULE #
##############

subUI <- function(id) {
  ns <- NS(id)
  tagList(
    useShinyjs(),
    actionButton(ns("click"), "CLICK!")
  )
}

subServer <- function(id, enabled_container) {
  stopifnot(is.reactivevalues(enabled_container))

  
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        if(enabled_container$enabled) {
          enable("click")
        } else {
          disable("click")
        }
      })
    }
  )
}

# ____________________________________________
##############
# MAIN APP   #
##############
ui <- fluidPage(
  actionButton("toggle", "Toggle"),
  subUI("sub")
)

server <- function(input, output, session) {
  
  r <- reactiveValues()
  r$enabled <- TRUE
  
  
  subServer("sub", r )
  
  observeEvent(input$toggle, {
    r$enabled <- !r$enabled
  })
}

shinyApp(ui, server, options = list(
  launch.browser = TRUE
))