Passing data from a callback to another callback with dcc.Store component

I have a multi-tab / page application and I’d like to pass the data (a dictionary) returned by a function call in one callback to another callback. Here’s some code:

import dash
from dash import dcc
import dash_bootstrap_components as dbc


#app layout

layout = html.Div([

                                   dcc.input(id="comp"),

                                   dcc.Store(id="id1")

                                   html.Div(id='dummy-div')

])

# callbacks

app.callback1([
                            output('comp','value'),
                            output('dummy-div','value'),
                         ],
                         [
                           input('in1','value'),
                           input('in2','value')
                         ],
                        ):
def update(in1, in2):
       # function call

      res = func(in1, in2)

      # for reproducibility
      res = {'name':'xyz', 'addr':'123'}

       return (in2, res)

app.callback(output('id1', 'data'),
                       [
                         input('comp','value'),
                         input('dummy-div','value)
                       ],
                      ):
def store(store, dummy):
   
       # save to store component

      # for reproducibility
      res = {'name':'xyz', 'addr':'123'}
    
     return {'res': res,
                   'comp': 12
                  }
      

I get an dash exception when I run the above code:

raise exceptions.InvalidCallbackReturnValue(
dash.exceptions.InvalidCallbackReturnValue: The callback for `[<Output `dummy-div.value`>]`
returned a value having type `list`
which is not JSON serializable.


The value in question is either the only value returned,
or is in the top level of the returned list,

and has string representation
`[{'Name':'xyz','Address':'123'........}]`

In general, Dash properties can only be
dash components, strings, dictionaries, numbers, None,
or lists of those.

Basically, I’d like to save res which is dictionary returned by the function invoked to dcc.Store component. I’d need to have two separate callbacks because of the way app is structured. How do I pass res to the callback that saves to dcc.Store component?

Hi,

I am a bit confused by your code. Could you provide a reproducible example? For instance, “dummy-div” seems to be a div, but there is no props value in html.Div (don’t you mean “children”?).

I am using property “value” for “dummy-div” and attempting to save res which is a dict to it. Are you suggesting using children instead?

@jlfsjunior can you check the code now? Should be able to reproduce.

@AnnMarieW would appreciate it if you can share any thoughts on this.

It is much better, thanks!

Yes, you will get an error if you try to pass “value” to a html.Div, but changing to “children” won’t be of much help, since res is a dictionary and you are not allowed to pass them to “children” (just numbers, strings, other components or lists of them).

If “dummy-div” has no other function than hold the data (i.e. you don’t want to display its children), then I would consider replacing it with another dcc.Store component. Something like:

from dash import Dash, dcc, html, Output, Input
import dash_bootstrap_components as dbc

app = Dash(__name__)

app.layout = html.Div(
    [
        dcc.Input(id="comp"),
        dcc.Dropdown(
            id="in1",
            options=[{"value": i, "label": i} for i in ["a", "b", "c"]]
        ),
        dcc.Dropdown(
            id="in2",
            options=[{"value": i, "label": i} for i in ["a", "b", "c"]]
        ),
        dcc.Store(id="id1"), 
        dcc.Store(id="new-dummy-div")
    ]
)

# callbacks
@app.callback(
    [
        Output("comp", "value"),
        Output("new-dummy-div", "data"), # this can have a dict
    ],
    [Input("in1", "value"), Input("in2", "value")],
)
def update(in1, in2):
    res = {"name": in1, "addr": in2}

    return (in2, res)


@app.callback(
    Output("id1", "data"),
    [Input("comp", "value"), Input("new-dummy-div", "data")],
)
def store(store, dummy):

    print(dummy)

    # for reproducibility
    res = {"name": "xyz", "addr": "123"}

    return {"res": res, "comp": 12}


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

If you still want to show the data in “new-dummy-div”, then you need to transform the dict in a way that can be taken in a html.Div or another component. For instance, transforming it to a string via json.dumps(res).

1 Like