✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

dcc.Store data not accessible when used in dcc.Tabs

Hey there,

I’m trying to make a Single Page Application thanks to dcc.Tabs component and I want my user to retrieve there data when they come back to a tab they already “worked” on.

For the moment, each time I come back to a Tab I’ve “worked” on (by refreshing the page, or switching of tab), the data is not accessible.

On the documentation example, you can relad the page or open it in a new tab and still keep the localy or memory stored data. I haven’t succed to have the same behaviour why using the dcc.Tabs component:

Anyone having faced the same problem or knowing what happend here ?

here the code of this demo-app:

import dash

import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Output, Input, State
from dash.exceptions import PreventUpdate

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.config['suppress_callback_exceptions']=True

app.layout = html.Div([

    html.Div([
        dcc.Tabs(id="tabs", value='/app1', children=[
             dcc.Tab(label='gna', value='/app1'),
            dcc.Tab(label='gnou', value='/app2'),
        ])
    ]),

    html.Br(),

    html.Div(id='page-content')
])

layout = html.Div([

    dcc.Store(id='memory'),
    dcc.Store(id='local', storage_type='local'),
    dcc.Store(id='session', storage_type='session'),

    html.Div([
        html.Button('Click to store in memory', id='memory-button'),
        html.Button('Click to store in localStorage', id='local-button'),
        html.Button('Click to store in sessionStorage', id='session-button')
    ]),

    html.Div([
        html.Table([
            html.Thead([
                html.Tr([
                    html.Th('Memory clicks'),
                    html.Th('Local clicks'),
                    html.Th('Session clicks')
                ])
            ]),
            html.Tbody([
                html.Tr([
                    html.Td(0, id='memory-clicks'),
                    html.Td(0, id='local-clicks'),
                    html.Td(0, id='session-clicks')
                ])
            ])
        ])
    ])
])


@app.callback(Output('page-content', 'children'), [Input('tabs', 'value')])
def display_page(pathname):
    if pathname == '/app1':
         return layout
    elif pathname == '/app2':
        return html.Div('Here is the first POC of the python backtest GUI')
    else:
        return html.Div('oOOouups ; I ; did it again...')


 for store in ('memory', 'local', 'session'):

    @app.callback(Output(store, 'data'),
              [Input('{}-button'.format(store), 'n_clicks')],
              [State(store, 'data')])
    def on_click(n_clicks, data):
        if n_clicks is None:
            raise PreventUpdate

        data = data or {'clicks': 0}

        data['clicks'] = data['clicks'] + 1
        return data

    @app.callback(Output('{}-clicks'.format(store), 'children'),
              [Input(store, 'modified_timestamp')],
              [State(store, 'data')])
    def on_data(ts, data):
        if ts is None:
            raise PreventUpdate

        data = data or {}

        return data.get('clicks', 0)


if __name__ == '__main__':
    app.run_server(debug=True, port=8077, threaded=True)

some solutions in this topic: Is there a way to synchronize dropdowns across tabs