-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Hi again @pmcharrison,
Sorry to be bringing up another issue so soon. This is actually something I've known about for a few years, but didn't bring up because I had workarounds. Nonetheless, it keeps catching me out in different forms and @KilianSander urged me to report it.
Basically, the function to the reactive_page fun argument calls twice, causing many forms of unexpected behaviours.
For instance, consider this:
make_test(
join(
reactive_page(function(state, ...) {
current_time <- as.character(Sys.time())
set_global("test", current_time, state)
one_button_page(current_time)
}),
reactive_page(function(state, ...) {
text <- get_global("test", state)
one_button_page(text)
})
)
)
I would expect the second reactive_page to display the value I set on the state object in the first reactive_page. However, it does not.
The same does not apply to a code_block, which gives me the behaviour I would expect (the reactive_page shows the value I set in the code_block and retrieve later):
make_test(
join(
code_block(function(state, ...) {
current_time <- as.character(Sys.time())
cat("Current time is ", current_time)
set_global("test", current_time, state)
Sys.sleep(5)
}),
reactive_page(function(state, ...) {
text <- get_global("test", state)
# Should be current time.. (and it is)
one_button_page(text)
})
)
)
So, one workaround, is to always use a code_block to set a value and reactive_pages only to retrieve values. However, in principle I think you should be able to set a value in a reactive_page and expect it to persist. I have found many use cases where I end up wanting to set a value on the state object in a reactive_page, usually updating moving values on the fly, like incrementing a page, which leads to strange results, like this, incrementing in twos:
make_test(
join(
code_block(function(state, ...) {
set_global("page_no", 1, state)
}),
reactive_page(function(state, ...) {
page_no <- get_global("page_no", state)
# Update for next page
set_global("page_no", page_no + 1, state)
one_button_page(paste0("This is page number: ", page_no))
}),
reactive_page(function(state, ...) {
page_no <- get_global("page_no", state)
one_button_page(paste0("This is page number: ", page_no))
})
)
)
If you really to use two reactive_pages, you can do something like:
make_test(
join(
reactive_page(function(state, ...) {
current_time <- as.character(Sys.time())
if(is.null(psychTestR::get_global("reactive_page_called", state))) {
set_global("test", current_time, state)
}
psychTestR::set_global("reactive_page_called", TRUE, state)
cat("first page: ", current_time, "\n")
one_button_page(current_time)
}),
reactive_page(function(state, ...) {
text <- get_global("test", state)
cat("second page: ", text, "\n")
one_button_page(text)
})
)
)
Here you make sure that the reactive_page function firing twice doesn't set the value twice. But it's a bit of a hacky workaround (which has ended up in some of my code libraries, however). This last example also shows how the reactive_page fun gets called once on the page rendering and once again on clicking the Next button.
Anyway, I just wanted to make you aware about this. I wonder if something can be done to stop this undesirable behaviour?