-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
freezeReactiveValue() and indirect dependencies #2946
Comments
Thanks for the report! I actually don’t believe I’ve come across this before. I think it’d be easy enough to invalidate on freeze, we’d have to think carefully about the downstream effects though. (Especially the edge case where the value of the input before and after the freeze is identical, which may already be a problem—I think at least it used to be but maybe we fixed it?) |
Maybe invalidating on freeze and also invalidating on thaw, plus automatic thawing when the session is flushed next? See also #1791 |
Wouldn't this mean that the value is invalidated when the session is flushed next? Why isn't it enough to invalidate on freeze? Sorry if these are stupid questions, I'm not a Shiny expert. |
Invalidating during freeze will cause the dependent output to show blank instead of an error (that's good). However, if the updateCheckboxGroupInput call doesn't actually cause the value to change (i.e. the existing and new values are identical) then the dependent output will stay blank (that's bad) without another invalidation. I'll take a crack at this on Monday. |
BTW, the scenario I referenced in my previous comment can be seen in #1791, the second example app I posted. |
Yes, I've read through #1791 and also ran the code given there, but I didn't really understand how it was related to the issue here. But your comment
made it clear that #1791 would also arise when invalidating on freeze, so that another invalidation (upon thaw) is needed. |
By
(see your post above), you would ensure that the value is not invalidated anymore when the session is flushed next? Then this was another misunderstanding by myself when I asked
|
1. freezeReactiveValue(input, "x") is called, inside a renderUI or in an observer that then calls updateXXXInput 2. Some reactive output tries to access input$x, this takes a reactive dependency but throws a (silent) error 3. When the flush cycle ends, it automatically thaws What's *supposed* to happen next is the client receives the new UI or updateXXXInput message, which causes input$x to change, which causes the reactive output to invalidate and re-run, this time without input$x being frozen. This works, except when the renderUI or updateXXXInput just so happens to set input$x to the same value it already is. In this case, the client would detect the duplicate value and not send it to the server. Therefore, the reactive output would not be invalidated, and effectively be "stalled" until the next time it is invalidated for some other reason. With this change, freezeReactiveValue(input, "x") has a new side effect, which is telling the client that the very next update to input$x should not undergo duplicate checking.
#3055 doesn't fix this problem, but it makes it so the only fix that's needed is invalidate on freeze (I believe). |
1. freezeReactiveValue(input, "x") is called, inside a renderUI or in an observer that then calls updateXXXInput 2. Some reactive output tries to access input$x, this takes a reactive dependency but throws a (silent) error 3. When the flush cycle ends, it automatically thaws What's *supposed* to happen next is the client receives the new UI or updateXXXInput message, which causes input$x to change, which causes the reactive output to invalidate and re-run, this time without input$x being frozen. This works, except when the renderUI or updateXXXInput just so happens to set input$x to the same value it already is. In this case, the client would detect the duplicate value and not send it to the server. Therefore, the reactive output would not be invalidated, and effectively be "stalled" until the next time it is invalidated for some other reason. With this change, freezeReactiveValue(input, "x") has a new side effect, which is telling the client that the very next update to input$x should not undergo duplicate checking.
1. freezeReactiveValue(input, "x") is called, inside a renderUI or in an observer that then calls updateXXXInput 2. Some reactive output tries to access input$x, this takes a reactive dependency but throws a (silent) error 3. When the flush cycle ends, it automatically thaws What's *supposed* to happen next is the client receives the new UI or updateXXXInput message, which causes input$x to change, which causes the reactive output to invalidate and re-run, this time without input$x being frozen. This works, except when the renderUI or updateXXXInput just so happens to set input$x to the same value it already is. In this case, the client would detect the duplicate value and not send it to the server. Therefore, the reactive output would not be invalidated, and effectively be "stalled" until the next time it is invalidated for some other reason. With this change, freezeReactiveValue(input, "x") has a new side effect, which is telling the client that the very next update to input$x should not undergo duplicate checking.
Seems like this and #1791 can be closed now? |
That's true, at least the issue reported here does not occur anymore when using shiny version 1.5.0.9005 (from GitHub). Thanks a lot! I haven't checked #1791, though. |
In my opinion,
freezeReactiveValue()
has a crucial drawback (and I guess this also applies tofreezeReactiveVal()
though I haven't tested it yet):Only reactive expressions depending directly on the object being freezed will quit with a silent error as done with
req(FALSE)
. Reactive expressions depending indirectly on the object being freezed won't realize that they should also quit with a silent error. Consider the following reproducible example which is a slightly modified version of the example from?freezeReactiveValue
:The difference to the original example from
?freezeReactiveValue
is thatoutput$plot
does not depend directly oninput$cols
, but only indirectly viacols_reactive()
. Thus, after having selected two columns frommtcars
and then switching topressure
,freezeReactiveValue()
does not help in avoiding the (temporary) error. This temporary error might not be a problem in this simple example, but I have an app where I need to avoid it. Of course it would be possible to manually notify all indirect dependencies to quit with a silent error, but this is a tedious and error-prone task and in my opinion, it breaks the concept of reactivity.I guess this drawback is already known, so I'm posting this as a feature request. I guess it will be quite complicated to fix this (so that also reactive expressions depending indirectly on the object being freezed will quit with a silent error), but it would be great if it could be managed somehow.
Edit 2020-09-16 by @jcheng5: I added
priority = 1
to the example to make it clear that even with the observers executing in the most desirable order, this is still a problem.The text was updated successfully, but these errors were encountered: