How does Dash react to using the Browser reload? (Or closing and reopening the window)

Can I implement the Dash app to either save the current state or start fresh when using the Browser reload button?

For some implementations it is critical that the current state does not get overwritten when reloading or accidentally closing the window and reopening it. Is it possible to give the app kind of a ‘final action before reload’ so that we can implement an emergency save function or something?

1 Like

As far as I know there are 2 main ways to save state between browsers closing / re-opening:

  1. Use dcc.Store: https://dash.plot.ly/dash-core-components/store

You can use storage_type='local' which will save the state to the browser, if the user opens the page you can use callbacks to read the Store and fill the appropriate values you need. I however have found this very finicky and don’t currently use it myself, but as far as I know it’s the only client side way of saving state between browser sessions.

  1. Save the state server side

I do something like this for most my apps:

def get_layout():
     user = get_user()
     user_state = get_user_state(user)
     # Layout Logic

app.layout = get_layout

And then for every state I want to save I do so in a callback:

@app.callback(output=foo, inputs=bar):
def my_app_function1(bar):
    user = get_user()
    set_user_state(user, 'function1', bar)
    # Callback logic

There are some examples of how one authenticates users with on this forum. Also instead of authenticating users you could do a similar trick with FlaskSession, but it would be limited to each Browser-Computer. All in all though it’s a lot of work you need to do on your side to get working.

2 Likes

Thanks a lot. :slight_smile: I kinda figured I could do it using the Store component. But I can’t implement another callback just for the refresh of the browser for every element of the app… The thing is, we already implemented a JSON save for everything that happens in the backend and load from that on startup of the app.

I was wondering if it was possible to just tell Dash to call a function the instant that the refresh is used. Because the refresh will already trigger the initial load from the file again, so I could just check in case of refresh if a special file has been generated and load from that instead of the old save file.

I don’t think anything is built in to Dash

It might be possible to build your own Dash Component to do this, as looking at the JavaScript API it’s the WindowEventHandlers.onbeforeunload which someone has built a React component for: GitHub - jacobbuck/react-beforeunload: 🚪 React component and hook which listens to the beforeunload window event.

Therefore I guess it would be possible to integrate with Dash: Build Your Own Components | Dash for Python Documentation | Plotly and build a callback on it? I imagine though when the user hit refresh they would see a dialog box that said something like “This page is asking you to confirm that you want to leave - data you have entered may not be saved.”.

Even then I don’t think there would be any guarantee this callback would actually execute, due to the user force closing the page or something else.

1 Like

Hmhm. There is no simple Store component that just saves the current state, correct? I would have to Store everything manually.

I mean, potentially, one could just use an interval to save the state every few seconds into a temp, however, that’s not too efficient…

@Damian thanks a lot for all the help so far. In our team, we had a more detailed discussion on what the challenges resulting from this are and there is still a fair bit of confusion. I’ll try to formulate them, maybe someone can answer. Potentially even somebody from plotly. (@chriddyp :pleading_face:)

The whole problem for me behind the refreshing is that your app might be connected to some real object which should preserve its current state when reloading/refreshing.

For the most parts, this worked by saving old states to a file and initializing all UI components from that, making sure nothing is lost. This only works on app-start though.

One thing I noticed while testing is that on Refresh the objects representing the real-life device stay in the same memory path, but refreshing resets them to their ‘default’ state, which is either the stuff from the previous save file or just some default value. I think I lack the proper understanding of the server architecture, but does Dash keep some sort of initial state of all objects to use in refreshs?

Another issue is that, when opening the app in more than one tab for example, they share the same objects, but the UI will never be the same. Is there a way to achieve this? What are the implications for deployment on a server? Does each user work on the same instance of the app? If not, can this be implemented, since technically, when working with physical devices, one will only have a single instance? And if it can be implemented, can it be done in a way that accounts for conflict other than using an interval which tries to get new values?

Is their perhaps a better way to work around these issues using e.g. gunicorn?

I guess the most appropriate formulation of the question would then be: How can one preserve the state of an app on close/refresh/reload/with-multiple-users most efficiently?

EDIT: I guess it is also related to Is classical State-less architecture suitable for Data Science products?

Might have missed something related to the refreshing:

https://dash.plot.ly/live-updates

Trying now what’s mentioned under Updates on page load

EDIT: Did not help.

Yeah, it seems like the level you want to preserve state is more like an offline web app which is way outside the scope of what Dash provides.

Dash if you think about is a glorified client-request server-response web page framework, and that makes it simple to build stuff but also have soft and hard real world limitations.

What I can tell you is that my (somewhat complex) web application that lets users configure their own Dashboards I preserve this state through a minimal number of callbacks saving to server side object store and then app.layout points to a function which reads out of this store. But I don’t have to support more than a few users, so I haven’t had to care about scale.

I guess that’s the extent of it then at least without using the commercial offers of plotly.

Have you had any experience with other python based UIs which incorporate browser based layouting? Because that to me is the brilliance of Dash at the moment. I though about using Electron, but it seems it is terribly annoying to incorporate it with a python server. (See https://www.fyears.org/2017/02/electron-as-gui-of-python-apps-updated.html)

HI @klnrdknt
Facing the same issue, is there any solution so that no need to save state for every component manually?
OR any trigger callback on page reload?

@mukul did you find any solutions?