Skip to content

reactive_page function calling twice causing undesirable behaviour #119

@sebsilas

Description

@sebsilas

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions