闪亮:更新输入而不会触发反应式?

时间:2019-02-06 18:39:25

标签: r shiny reactive-programming

是否有可能在不触发反应式的情况下更新输入?

下面我举一个简单的例子。目的是在不更改主面板中的值的情况下更新滑块。再次更改滑块时,应再次将其转发给相关的电抗器。

该问题和基本用例类似于以下问题:R shiny - possible issue with update***Input and reactivityUpdate SelectInput without trigger reactive?。与这些问题类似,在我的用例中,有一个反应取决于两个输入。我想根据另一个来更新其中一个输入,这导致反应式被计算两次。但是,这两个问题都是通过仅选择性地更新输入来解决的。在我的用例中这是不可能的,因为我想通过更新输入向用户显示一些信息。

如果在没有触发反应式的情况下没有更新输入的可能性,我将针对我的用例提出一个后续问题。

示例

library(shiny)

ui <- fluidPage(
   titlePanel("Update Slider - Isolate reaction?"),

   sidebarLayout(
      sidebarPanel(
         sliderInput("bins",
                     "Number of bins:",
                     min = 1,
                     max = 50,
                     value = 30),
         actionButton("set1", "set slider 'bins'$value=20"),
         actionButton("set2", "'ISOLATED' set slider 'bins'$value=20 ")
      ),

      mainPanel(
         textOutput("sliderValue")
      )
   )
)

# Define server logic 
server <- function(input, output, session) {
   output$sliderValue <- renderText(input$bins) 

   observeEvent(input$set1,{
     updateSliderInput(session,"bins",value=20)
   })
   observeEvent(input$set2,{
     ## Is there any possibility to update the slider without 'sliderValue' changing?
     #isolate does not work
     isolate(
       updateSliderInput(session,"bins",value=20 )
       )
   })
}

shinyApp(ui = ui, server = server)

2 个答案:

答案 0 :(得分:1)

这是一个刺,尽管感觉使用过时的数据可能会产生副作用。使用以下 diff

 # Define server logic
 server <- function(input, output, session) {
-  output$sliderValue <- renderText(input$bins)
+  output$sliderValue <- renderText({ saved_bins(); })

+  update <- reactiveVal(TRUE)
+  saved_bins <- reactiveVal(30)
+
+  observeEvent(input$bins, {
+    if (update()) saved_bins(input$bins) else update(TRUE)
+  })
   observeEvent(input$set1,{
     updateSliderInput(session,"bins",value=20)
   })
   observeEvent(input$set2,{
     ## Is there any possibility to update the slider without 'sliderValue' changing?
     #isolate does not work
+    update(FALSE)
-    isolate(
       updateSliderInput(session,"bins",value=20 )
-    )
   })
 }

该方法:使用两个新的反应性值,一个用于存储渲染中使用的数据(saved_bins,另一个用于存储是否应更新该数据的update。相反,所有依赖input$bins的事物都应该依赖saved_bins()。通过使用附加的observeEvent,当您明确地将前置{设置为一次“不级联”时,反应性将总是级联,如最初所需的 。 {1}}。

下面的完整代码:

update(FALSE)

答案 1 :(得分:0)

首先要归功于@ r2evans的解决方案。

在许多禁止它的头疼中,存在口头bal撞的危险,为避免双重观察者,您可以使用全局分配。明智的做法是使用比' update '更少的通用名称。

library(shiny)

ui <- fluidPage(
  titlePanel("Update Slider - Isolate reaction?"),
  
  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30),
      actionButton("set1", "set slider 'bins'$value=20"),
      actionButton("set2", "'ISOLATED' set slider 'bins'$value=20 ")
    ),
    
    mainPanel(
      textOutput("sliderValue")
    )
  )
)

# Define server logic 
server <- function(input, output, session) {
  output$sliderValue <- renderText({ saved_bins(); }) 
  
  saved_bins <- reactiveVal(30)
  
  observeEvent(input$bins, {
    if (update) saved_bins(input$bins) else update <<- TRUE
  })
  observeEvent(input$set1,{
    updateSliderInput(session,"bins",value=20)
  })
  observeEvent(input$set2,{
    ## Is there any possibility to update the slider without 'sliderValue' changing?
    #isolate does not work
    update <<- FALSE
    updateSliderInput(session,"bins",value=20)
  })
}

shinyApp(ui = ui, server = server)