闪亮:更新输入而不触发反应?
Posted
技术标签:
【中文标题】闪亮:更新输入而不触发反应?【英文标题】:shiny: Update input without reactives getting triggered? 【发布时间】:2019-06-30 19:24:07 【问题描述】:是否有可能在不触发反应器的情况下更新输入?
下面我举一个最小的例子。目的是在不更改主面板中的值的情况下更新滑块。当滑块再次更改时,应再次将其转发给相关的反应器。
问题和底层用例类似于以下问题:R shiny - possible issue with update***Input and reactivity 和 Update 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)
【问题讨论】:
【参考方案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)
【讨论】:
以上是关于闪亮:更新输入而不触发反应?的主要内容,如果未能解决你的问题,请参考以下文章