dash-labs icon indicating copy to clipboard operation
dash-labs copied to clipboard

Passing data between pages via a dcc.Store

Open stevej2608 opened this issue 2 years ago • 3 comments

Hi, I'm not sure if this is a Pages plugin issue or dcc.Store. I have a two page demo. One page accepts an email, the associated callback outputs the email to a store and forces a redirect:

login.py

email = dcc.Input(id='email', name='email', type='email', placeholder="Enter email")
button = html.Button('Sign In', type='submit', id='btn')
redirect = dcc.Location(id='redirect', refresh=True)

layout = html.Div([email, button, redirect])

@callback(Output('redirect', 'href'), Output('store', 'data'), State('email', 'value'), Input('btn', 'n_clicks'))
def email_cb(email, clicks):
    _redirect = NO_UPDATE
    _store = NO_UPDATE
    if clicks:
        _redirect = '/user'
        _store = {'email' : email}

    return _redirect, _store

The user page has a callback that accepts the stored email value and updates the page:

user.py

@callback(Output('user', 'children'), Input('store', 'data'))
def _login_cb(data):
    print('_login_cb')
    ctx = callback_context
    if not ctx.triggered:
        print('  NOT triggered')
    if data:
        print('  Valid store data available')
        return f"Hello {data['email']}"
    else:
        return NO_UPDATE

The page updates with the email correctly. The problem is ctx.triggered is false even when valid store data is available. The print message output is:

_login_cb
  NOT triggered
  Valid store data available

app.py

store = dcc.Store('store', storage_type='session')

app = dash.Dash(
    __name__, plugins=[dl.plugins.pages], external_stylesheets=[dbc.themes.BOOTSTRAP]
)

app.layout = dbc.Container(
    [store, dl.plugins.page_container],
    fluid=True,
)

Any ideas?

stevej2608 avatar May 04 '22 08:05 stevej2608

Hi @stevej2608 I don't see anything obviously wrong. Would you be able to share a link to your demo and I can take it for a spin?

AnnMarieW avatar May 04 '22 15:05 AnnMarieW

Thanks for taking a look. Example code is here:

/docs/demos/multi_page_store

stevej2608 avatar May 04 '22 15:05 stevej2608

Hi @stevej2608 ,

This is a great question and thanks for the example. I can verify what you reported - An update to dcc.Store on one page does not trigger a callback when it's used as an input to a callback on another page.

This is not just a dash-labs pages plugin thing. It's the same with the "old" way of creating a multi-page dash app. I even checked the "old old" way in dash <v2 -- using @app.callback instead of @callback in the pages folder.

I don't think this is a bug though. It's intuitive to expect that it would trigger the callback since it's an Input (and not State). However, when the dcc.Store is updated on one page, the component from the other page that would trigger this callback does not exist in the browser - so it's not possible for that callback to be triggered.

Based on your example, you are trying to get authentication working. You may find this example helpful https://github.com/plotly/dash-labs/issues/90#issuecomment-1110510797

AnnMarieW avatar May 05 '22 14:05 AnnMarieW