【问题标题】:shiny: Update input without reactives getting triggered?闪亮:更新输入而不触发反应?
【发布时间】:2019-06-30 19:24:07
【问题描述】:

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

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

问题和底层用例类似于以下问题: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)

【问题讨论】:

    标签: r shiny reactive-programming


    【解决方案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,当您显式设置带有前置update(FALSE) 的一次性“不级联”时,反应性将始终按照最初需要的方式级联除了 .

    完整代码如下:

    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(); }) 
    
      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)
        updateSliderInput(session,"bins",value=20)
     })
    }
    
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 酷。虽然我有点想知道额外的观察者最终会付出多大的代价......也许从长远来看,可能有可能将它直接包含在 updateXXXInput-commands 中?至少我把它加入了愿望清单:github.com/rstudio/shiny/issues/2324
    • 我理解您的担忧,尽管这是一个“简单的”一维中间observe,如果这有意义的话。只要对input$bins 没有其他反应,我认为双重反应的风险即使不是零也很小。
    【解决方案2】:

    首先感谢@r2evans 的解决方案。

    冒着被许多禁止它的校长口头抨击的风险,为避免双重观察者,您可以使用全局分配。不过,使用比 '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)
    

    【讨论】:

      猜你喜欢
      • 2020-12-28
      • 2020-02-08
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 2015-10-29
      • 1970-01-01
      • 2020-08-01
      相关资源
      最近更新 更多