【问题标题】:reactive invalidation based on (boolean) reactive conditional基于(布尔)反应性条件的反应性失效
【发布时间】:2019-08-04 08:06:39
【问题描述】:

我有一个反应式rv 和一个反应式布尔值rv.haschanged,定义如下:

rv <- reactive({
  rv.haschanged()

  rv.haschanged(FALSE)

  cars[sample.int(nrow(cars), 1),] # return cars dataset as an example
})

rv.haschanged <- reactiveVal(FALSE)

现在有一些观察者,例如,可以将rv.haschanged 设置为TRUE

observe({
    # do something...

    rv.haschanged(TRUE)
})

我想要的是 rv 仅在 rv.haschanged 更改为 TRUE 时更新自身(而不是在 rv.haschanged 更改为 FALSE 时)。上面代码的问题是它会更新rv两次。一次在观察者执行rv.haschanged(TRUE) 之后,又一次由于rv.haschanged(FALSE)

有什么简洁直观的习语可以实现上述目标?

编辑:基本上,我想要的只是使观察者中的rv 无效,因此它会安排重新执行。

【问题讨论】:

  • rv 应该什么时候更新?如果您不希望它因更改rv.haschanged 而失效,您可以将其更改为eventReactive,这样它只会因更改其eventExpr 中的内容而失效
  • @divibisan 确实如此。 rv 是响应式的,当 rv.haschangedTRUE 时它应该更新。当rv.haschangedFALSE 时,它不应更新。

标签: r shiny


【解决方案1】:

做你想做的最好的方法是isolate在你的反应表达式中使用rv.haschanged,这样它们就不会使表达式无效,然后使用一个中间反应值,可以合并你想要的逻辑。

我们将创建一个名为 check 的新反应值,而不是使用 rv.haschanged() 中的更改来使您的反应式表达式无效,它仅包含一个计数器,该计数器在 rv.haschanged 更改 AND 为 TRUE 时递增

check <- reactiveVal(0)
observeEvent(rv.haschanged(), if (rv.haschanged() == TRUE) check(check() + 1))

现在,我们可以使用 isolate 在反应式表达式中隔离 rv.haschanged()

rv <- reactive({
    check()
    isolate(rv.haschanged(FALSE))
    cars[sample.int(nrow(cars), 1),] # return cars dataset as an example
})

或将其更改为eventReactive,其工作方式类似于reactive,但隔离valueExpr 中的所有内容:

rv <- eventReactive(check(), {
    rv.haschanged(FALSE)
    cars[sample.int(nrow(cars), 1),] # return cars dataset as an example
})

这有点小技巧,但据我所知,没有办法让反应式表达式的失效短路:它要么有效(未更改),要么无效(已更改)。在 Shiny 中工作时对我有好处的是将响应式表达式分解为更小的块(尤其是当它们包含时间密集型任务时),以最大限度地减少在某些内容失效时必须重新运行的代码量。

【讨论】:

  • 谢谢! +1,但check() 对我来说感觉有点老套。如果几天后没有人给出更好的答案,我会接受你的。
  • 如果你改用reactiveValues,它就不会那么难看,所以你不需要另一个单独的reactiveVal来浮动。你也可以给它一个更具描述性的名字,比如rv$rv.haschanged.check
  • 但是,是的,这有点像 hack。如果有更好的方法,我真的很想看到
  • 我添加了一个答案。尚未对其进行测试,但不知道您对此有何看法。
  • @DavorJosipovic 我想我误解了你,让你的问题比实际情况更复杂。你的代码应该防止rv 运行两次,但如果有其他任何东西将rv.haschanged 更改为FALSE,它就会失效。如果rv.haschanged 更改为TRUE,我的解决方案将只运行rv。这似乎不是您想要的,是吗?
【解决方案2】:

这行得通:

rv <- eventReactive(rv.haschanged(), {      
  rv.haschanged(NULL)

  cars[sample.int(nrow(cars), 1),] # return cars dataset as an example
})

rv.haschanged <- reactiveVal(NULL)

还有观察者:

observe({
    # do something...

    rv.haschanged(TRUE)
})

这利用了eventReactiveignoreNULL = TRUE 选项。所以我们不使用FALSE,而是使用NULL

请注意,这个will not work if multiple objects are put in the eventExpr argument

【讨论】:

    猜你喜欢
    • 2016-10-20
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 2021-05-26
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    相关资源
    最近更新 更多