【问题标题】:R Shiny: unwanted reactivity using htmlOutput and observeEventR Shiny:使用 htmlOutput 和 observeEvent 的不需要的反应
【发布时间】:2020-11-17 02:31:19
【问题描述】:

问题总结

我进行了彻底的搜索,但找不到提出相同问题的人。我正在使用 R Shiny 制作一个化学反应模拟网页,并希望向用户显示来自最新模拟的变量。因此,用户可以更改输入变量,但在再次按下操作按钮并模拟另一个反应之前,显示的“变量摘要面板”不应更改。

使用 observeEvent、renderUI 和 htmlOutput 实现应该相当简单,但我一直遇到“变量摘要面板”对输入变量的变化做出反应的问题,即使没有按下操作按钮。下面是一些示例代码:

示例代码

library(shiny)
library(tidyverse)

ui <- fluidPage(
   # input variable
   tags$p("Reaction Temperature  (ºC)"),
   sliderInput("temp_initial",NULL,min = 20,max = 70,value = 25),
   # action button
   actionButton(inputId = "go", label = "Generate Reaction Simulation"),
   # summary panel
   wellPanel(
       tags$p(tags$strong("Simulated input variables")),
       htmlOutput("blurb_explanation")
   )
)
server <- function(input, output, session) {
    # render summary panel text
    observeEvent(input$go, ({
        output$blurb_explanation <- renderUI(
           HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial))
        )
    })
    )
}
# Run the application 
shinyApp(ui = ui, server = server)

尝试的解决方案

我可能只是对 Shiny 反应性缺乏了解,因为我对 R Shiny 还很陌生。我的理解是,如果我将 input$go 作为响应式表达式传递给 observeEvent,则函数的主体将不会运行,直到再次按下 go 按钮。现在,在创建摘要面板后,滑块中的任何更新仍会更改 HTML 输出。

我尝试将函数体包装在一个隔离函数中,使 observeEvent 依赖于其他反应性变量,但似乎没有什么可以解决这个反应性问题。

提前感谢您的帮助,这是我的第一个 Stack Overflow 问题,如果有任何不清楚的地方请告诉我,我可以尝试解决。

【问题讨论】:

    标签: r shiny shiny-reactivity


    【解决方案1】:

    默认情况下,您的 renderUI - 就像任何 renderXXXX 一样 - 更新以响应对 any 的更改(如果它包含反应式)。因此,它会响应您的actionButtonsliderInput 的点击而更新。你无法摆脱它对sliderInput的依赖,所以你需要将isolaterenderUIsliderInput的更改中删除。幸运的是,isolate 函数可以为您做到这一点。

    这是您的服务器功能的工作版本:

    server <- function(input, output, session) {
      # render summary panel text
      observeEvent(input$go, ({
        output$blurb_explanation <- renderUI(
          isolate(HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial)))
        )
      })
      )
    }
    

    更简单的版本将不再需要renderUIobserveEvent

    server <- function(input, output, session) {
      # render summary panel text
        output$blurb_explanation <- renderText({
          input$go
          isolate(HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial)))
        })
    }
    

    renderText 仍然依赖于actionButton,因此它会根据对按钮的点击进行更新。但是actionButton 不产生任何输出。 htmlOutputsliderInput 的依赖仍被 isolate 掩盖,因此输出仅更新为按钮单击。

    PS。欢迎来到 SO。

    【讨论】:

    • 谢谢!我没有尝试将隔离放在渲染函数的文本内,只是放在外面。您的解决方案有效 - 我选择 renderUI 的原因是因为实际的摘要面板大约有 10 行,使用 htmlOutput 更容易中断。感谢您的帮助!
    猜你喜欢
    • 2017-11-06
    • 2021-05-23
    • 2022-01-19
    • 2021-11-14
    • 2018-11-18
    • 2018-12-05
    • 2018-12-14
    • 2019-08-01
    • 2021-02-13
    相关资源
    最近更新 更多