Dynamic components creation cause callback outputs duplicates

So!
I am working on a project where I need to create the same component with a different idea a couple of times.
and for each component, I am creating the same callback just with a different output

def createCallback(id):
    app.callback(
         Output(id, 'children'),
         Input(id, 'n_clicks')
    )(callback_function)

def callback_function(n_clicks):
    print(n_clicks)
    return n_clicks

The code is something I came on the spot but does the job as an example for the callback creation.
Now I pass all of my objects creation as functions and to the layout, I pass a function so it will render the app from scratch each time a user is opening the app / refreshing it.

app.layout = generateAppLayout

and because I create the app from scratch it creates the callbacks again and thus the “Duplicate callback outputs” come to the picture. (i have to refresh the app because they have a button where they upload data to the database and I need to load the new data that was inserted by the user)

any idea how I can fix this problem? I thought about a few ideas which I have no idea how I can implement

  1. find a way to check if a callback exists with a specific output and create the callback only if it doesn’t exist
  2. find a way to delete the callback if the app is reloaded

thanks for taking the time to read! if you know how to implement the ideas I wrote/got an idea of your on please do share!

Hi,

I think that the canonical solution to your problem is to use a pattern-matching callback.

Please take a look at the docs and follow up if this isn’t what you are looking for or if you have questions regarding how to implement it for your particular case.

it won’t work for my problem, tho it’s a very cool way of working which I didn’t know about and have use for another feature in my project so thanks anyhow!
it won’t work because I am creating my callback in a generic way and for multiple pages with very different ids.
for example, I have 2 pages
Business, travel
I will have 1 component with the id
BusinessInsight1
and another
travelInight1
and I can’t try and get them by matching insight1/just insight because I have more components and ids which have the same string in them.
so I can’t see it working as an answer for me.

Could you share with us a minimal example of layout/callback that you want to make work with your current approach?

I am a bit confused because if you have these two pages, you could use the “page id” (business, travel) as index of your pattern-matching component, like in:

# Just an example....
def create_page(page_id):
    return html.Div(
        [
            html.Button(
                "Update"
                id={"type": "button", "index": page_id}
            ),
           html.Div(id={"type": "div-to-be-updated", "index": page_id})
        ]


@app.callback(
    Output(id={"type": "div-to-be-updated", "index": MATCH}, 'children'),
    Input(id={"type": "button", "index": MATCH}, 'n_clicks'),
)
def callback_function(n_clicks):
    print(n_clicks)
    return n_clicks

Yes here is a bit of my code, it’s hard to send it all because it’s on a private network so I have to copy it by hand.

def createSaveInsightHandler(insight_TextArea_ids):
    outputList = [
        Output(f"{insight_TextArea_ids[0]}", "children"),
    ]

    inputList = [
        # If the save button is clicked it will update the insight in the DB
        Input('saveInsightsButton','n_clicks'),
    ]

    stateList = []

    for insight_id in insight_TextArea_ids:
        stateList.append(State(f"{insight_id}", "value"))
    stateList.append(State("url","pathname"))
    stateList.append(State('graphDate', 'children'))
    app.callback(
        outputList,
        inputList,
        stateList
    )(saveButtonHandler)

def saveButtonHandler(*args):
    pass

The problem is that the insights id created with the page id like this:
f"insight{page_id}{index}" and so we get
“insightHadas1”
or
“insightTokov2”
or
“insightRoll3”
so I can’t use the same type or index because we have a third variable at play here.

no not really, my problem is different then his.

Ok, thanks for sharing this part of the code. It makes total sense now why you say you can’t simply use the pattern-matching callbacks.

You seem to have a quite large application, so pardon me if my advice won’t fit (again) the purpose of what you are doing. That said, I don’t think you need the “page_id” part in the id if your app layout is similar to a multi-page application described here, which seems to be the case as you are using State("url","pathname").

The reason is that if you are in page “Hadas”, none of the textareas with id=“insightTokov*” and so on will be available in the layout anyway, so there isn’t any point is creating individual callbacks at each page.

1 Like

That’s a great point! And it works! Thanks for helping!