Create a dcc.Store component inside callback

Hi guys,
I wanted to create a dcc.Store component with an id of “type”:xyz and “index”:abc inside a callback. In this callback I also create e.g. a dropdown menue with the same index. However, I always get the dash error “A nonexistent object was used in an Output of a Dash callback…” for the callback that should fill this storage.

If I move the creation of the storage into the layout of the app, everything works fine. So what I am currently doing is creating a lot of storages in the layout and hope that I never dynamically create more indices than that
*[dcc.Store(id={“type”: “store”, “index”: i}, storage_type=“session”) for i in range(20)]

Do you guys have any idea how I could solve this problem?

Best,
Julius

Hi @xaver the dynamic creation of the dcc.Store() should work. Can you provide a minimal example which reproduces your issue for us to have a look at?

Sadly I don’t get an min working example running. But at least I know now that it should work. I’ll keep trying it.

Essentially putting this into the layout works fine but creating this in a callback throws the error in the next callback.
dcc.Store(id={“type”: “store”, “index”: 0}, storage_type=“session”)

Hey @xaver, here an example to get you started:

from dash import Dash, html, Input, Output, Patch, dcc, MATCH


def create_content(idx):
    return html.Div([
        dcc.Store(id={"type": "store", "index": idx}),
        dcc.Dropdown(id={"type": "drop", "index": idx}, options=[1, 2, 3]),
        html.Div(id={"type": "output", "index": idx}, children=[]),
    ])


app = Dash(
    __name__,
    suppress_callback_exceptions=True
)


app.layout = html.Div([
    html.Button(id="btn", children="create Store + drop down"),
    html.Div(id="container", children=[])
])


@app.callback(
    Output("container", "children"),
    Input("btn", "n_clicks"),
    prevent_initial_call=True
)
def update(idx):
    patched = Patch()
    patched.append(create_content(idx))
    return patched


@app.callback(
    Output({"type": "output", "index": MATCH}, "children"),
    Input({"type": "drop", "index": MATCH}, "value"),
    prevent_initial_call=True
)
def generate_output(value):
    return {
        1: "option 1",
        2: "option 2",
        3: "option 3"
    }[value]


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

Maybe you were just missing the prevent_initial_call=True

mred pmcb

1 Like