dcc.Store in context of multi pages app

Hello The Dash community !

I working on multi pages app using dcc.Store component.

My understanding with dcc.Store is that component is declared once in app.py, then since dcc.Store gets loaded it get available in any page when needed,
I’m having trouble with following code.

app.py code.

app.layout = dbc.Container([
    html.Div([
        dcc.Store(id='store-1', data={}, storage_type='local'),
        dcc.Store(id='store-2', data={}, storage_type='local'),
        dcc.Store(id='store-3', data={}, storage_type='local'),
        dcc.Store(id='store-4', data={}, storage_type='local'),
        dcc.Store(id='store-5', data={}, storage_type='local'),
        dcc.Store(id='store-6', data={}, storage_type='local'),
        dcc.Store(id='store-7', data={}, storage_type='local'),
        dcc.Store(id='store-8', data={}, storage_type='local'),
        dcc.Store(id='store-9', data={}, storage_type='local'),
        dcc.Store(id='store-10', data={}, storage_type='local'),
        dcc.Store(id='store-11', data={}, storage_type='local'),
        dcc.Store(id='store-12', data={}, storage_type='local'),
        dcc.Store(id='store-13', data={}, storage_type='local'),
        dcc.Store(id='store-14', data={}, storage_type='local'),
        dcc.Store(id='store-15', data={}, storage_type='local'),
        dcc.Store(id='store-16', data={}, storage_type='local'),
        dcc.Store(id='store-list_dict', data={}, storage_type='local'),
        dcc.Store(id='store-words-list', data={}, storage_type='local'),
        dcc.Store(id='store-years-list', data={}, storage_type='local')
        ]),

        
    dbc.Row([
        dbc.Col([
            sidebar],
            xs=4,
            sm=4,
            md=2,
            lg=2,
            xxl=2),
        
        dbc.Col([
            dash.page_container],
            xs=8,
            sm=8,
            md=10,
            lg=10,
            xxl=10),
        ])
    ], 
    fluid=True
    )
        

if __name__ == '__main__':
    app.run(debug=True)

With following code I checked dcc.Store component “store-words-list-output” get loaded)

layout = dbc.Container([
    
    html.Div(
        [dcc.Store(id=f'store-{i}', data=new_list[i].to_dict('records')) for i in range(len(new_list))
        ]
        ),
    html.Div([dcc.Store(id='store-list_dict', data=l_of_lists)]),
    html.Div([dcc.Store(id='store-words-list', data=list_of_d_words)]),
    html.Div([dcc.Store(id='store-years-list', data=list_of_d_years)]),
    
    **html.Div(id='store-words-list-output', children=[]),**

Other code lines....


@callback(
    Output('store-words-list-output', 'children'),
    Input('store-words-list', 'data')
    )
def return_val(data):
    
    print(f'data: {data[0]['Stroke']}')
    return data[0]['Stroke']

This works fine, return list of dictionaries

Code from page_2, where the problem occurs:

dash.register_page(__name__,
                    path='/lri',
                    title='db-lri',
                    name='db-lri',
                    location="sidebar")

**layout = html.Div(id='store-words-output')**


**@callback(**
**    Output('store-words-output', 'children'),**
**    Input('store-words-list', 'data')**
**    )**
**def check(data):**
**    print(f'children: {data}')**
**    return data**

This code do not return anything ==> children: {}

I do not see where I am wrong…

I need help on this, I maybe wrong with principle

Thank you for your time on this !!

I can’t see anything in the code you’ve posted that includes an element with this ID in the layout.

I think it is in the layout as it is stated right there, no?

layout = html.Div(id=‘store-words-output’)

So the callback should return “data”,

callback(
Output(‘store-words-output’, ‘children’),
Input(‘store-words-list’, ‘data’)
)

I made some light changes, and made some checks,

In the app.py code:

app.layout = dbc.Container([
    html.Div([
        dcc.Store(id='store-1', data={}, storage_type='memory'),
....

        dcc.Store(id='store-words', data={}, storage_type='memory'),
        dcc.Store(id='store-years', data={}, storage_type='memory')
        ]),

Here is where stores get loaded in page_1

"""layout"""
layout = dbc.Container([
    
    html.Div(
        [dcc.Store(id=f'store-{i}', data=new_list[i].to_dict('records')) for i in range(len(new_list))
        ]
        ),
    html.Div([dcc.Store(id='store-list_dict', data=l_of_lists)]),
    html.Div([dcc.Store(id='store-words', data=list_of_d_words)]),
    html.Div([dcc.Store(id='store-years', data=list_of_d_years)]),
...

Here is where I made some checks in page_2

"""layout"""
layout = html.Div([
    html.Div(id='words-output', children=[]),
    dash_table.DataTable(id='table',
                         data=[],
                         page_size=10)
    ])


@callback(
    Output('words-output', 'children'),
    Input('store-words', 'data')
    )
def return_val(data):
    print(f'data_lri: {data}')
    return
    
    
@callback(
    [Output('table', 'data'),
     Output('table', 'columns')],
    Input('store-1', 'data')
    )
def df_table(data):
    df = pd.DataFrame(data)
    rows = df.to_dict('records')
    columns = [{"name": str(col), "id": col} for col in df.columns]
    
    print(f'columns: {columns}')
    return rows, columns

Here are results from callbacks:

data_lri: {}
columns: []

Nothing returned…

So, I get stuck there with no path to solve and understand where I am wrong

Thank you for your help on this !

Hi @Olivier_fr

If you have the stores defined in app.py, they are available to every page of the app. You don’t need to re-define them in each page layout.

Yes,

In app.py, I declare stores
In page_1, I load stores

In page_2, I just use stores as input to callback.

"""layout"""
layout = html.Div([
    html.Div(id='words-output', children=[]),
    dash_table.DataTable(id='table',
                         data=[],
                         page_size=10)
    ])


@callback(
    Output('words-output', 'children'),
    Input('store-words', 'data')
    )
def return_val(data):
    print(f'data_lri: {data}')
    return
    
    
@callback(
    [Output('table', 'data'),
     Output('table', 'columns')],
    Input('store-1', 'data')
    )
def df_table(data):
    df = pd.DataFrame(data)
    rows = df.to_dict('records')
    columns = [{"name": str(col), "id": col} for col in df.columns]
    
    print(f'columns: {columns}')
    return rows, columns

I am wrong somewhere, but do not see where,
Many thanks for tanks for your help on this !!

In your post above, you show the stores defined in app.py and in the layout of page_1

It’s hard to help with the code you posted., Can you make a complete minimal example? Posting it to GItHub would make it easy too.

Many thanks for your time on this,

I copied code in git hub,

Hope it helps as I really need to understsand what’s wrong here,

Thank you again

I think I have the answer…
Instead of loading stores in page_1.py, it must be done in app.py, then, indeed data get available for other pages.

Could you confirm that point ?

Thank you for your time !

I confirm :slightly_smiling_face:

2 Likes

Thank you so much for your help ! :grinning:

2 Likes