I have a fairly complex shiny app, and users have requested that they'd like the state to be automatically restored across sessions to the place where they left off before. Are there hooks to save and restore the state programmatically? In other words, I'd be constantly updating a disk file whenever the input state changes. When a new session starts, I'd retrieve the state from disk and update all the inputs.
I know this is an old discussion, but I wanted to chime in with a hack/solution I came up with recently. I had a similar request, though it was primarily due to periodic instability (network glitches, app errors, etc). The problem with doing this automatically is that you effectively have to observe
every input. It does not automatically reload a snapshot, as I did not have sufficient time to verify that it would not auto-reload in the middle of a valid session.
The module code is a bit long (and currently a little sloppy), but the gist of what I had to do:
- single-app sqlite database, single table, with
session$user
, the type of save (auto or manual), a timestamp, and the json-ified (jsonlite::toJSON
) list of snapshot-values; could easily be a more permanent db solution (postgres, mariadb, etc) - inputs:
-
checkboxInput
: autosave -
selectInput
: previously-stored snapshots - three
actionButton
: save-now, restore, expire-now (could be better)
-
- the server function is passed a reactive list of "interesting" inputs (as a reactive
dat()
) from the main app - new observe blocks:
-
observe
ondat()
(andinput$autosave
), storing the last-snapshot to check for "effectively different" and a minimum time since last save before auto-saving; does nothing if!input$autosave
; observeEvent(input$savenow, ...)
-
observeEvent(input$restore, ...)
using the selected snapshot -
observeEvent(input$expirenow, ...)
, actually opening a modal that confirms expiration; -
timestamps <- eventReactive
that looks for the DB connection as well as aninvalidateLater
to periodically look for snapshots saved to the DB from other same-user sessions; -
observeEvent(timestamps(), ...)
in order toupdateSelectInput
; and - optional
observe
withinvalidateLater
to auto-expire stale snapshots.
-
- server function returns a list similar to
dat()
that is updated with the restored snapshot (on which the main app shouldobserveEvent
and update inputs)
While I'm not averse in general to releasing the code, it was written in haste for a specific weekend flurry of activity, and really needs to be cleaned up for more general and well-behaved use. Because it tends to touch all (relevant) inputs simultaneously, it can cause a flurry of reactivity in the app, so poorly-controlled reactivity is quickly punished.
Possible extension: user-named snapshots, not just auto/manual.
This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.